Search code examples
c#visual-c++java-native-interface

Convert jbyte* to array<Byte>^


my c# code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SourceAFIS.Simple;
using System.Windows.Media.Imaging;


namespace TempSample
{
    public class TempletExtractorSample
    {
        // Inherit from Fingerprint in order to add Filename field
        [Serializable]
        class MyFingerprint : Fingerprint
        {
            public string Filename;
        }

        // Inherit from Person in order to add Name field
        [Serializable]
        class MyPerson : Person
        {
            public string Name;
        }


        static AfisEngine Afis;

        // Take fingerprint image file and create Person object from the image
        public static string getTemplate(byte[] byteArray, string name)
        {
            Console.WriteLine("Enrolling {0}...", name);

            // Initialize empty fingerprint object and set properties
            MyFingerprint fp = new MyFingerprint();
            //BitmapImage image = new BitmapImage(new Uri(filename, UriKind.RelativeOrAbsolute));


            BitmapImage image = new BitmapImage();
            image.BeginInit();
            image.StreamSource = new System.IO.MemoryStream(byteArray);
            image.EndInit();

            fp.AsBitmapSource = image;
            // Above update of fp.AsBitmapSource initialized also raw image in fp.Image
            // Check raw image dimensions, Y axis is first, X axis is second
            Console.WriteLine(" Image size = {0} x {1} (width x height)", fp.Image.GetLength(1), fp.Image.GetLength(0));


            // Initialize empty person object and set its properties
            MyPerson person = new MyPerson();
            person.Name = name;
            // Add fingerprint to the person
            person.Fingerprints.Add(fp);

            // Execute extraction in order to initialize fp.Template
            Console.WriteLine(" Extracting template...");
            Afis = new AfisEngine();
            Afis.Extract(person);

            // Check template size
            Console.WriteLine(" Template size = {0} bytes", fp.Template.Length);
            byte[] b = fp.Template;
            string base64String = System.Convert.ToBase64String(b, 0, b.Length);

            return base64String;
        }
    }
}

VC++ Code is

#include "stdafx.h"

#include "TempletGen.h"

#include "test5_TempletGenerator.h"

#include <string>
using System::Text::Encoding;

String^ toString(const char *chars){
    int len=(int)strlen(chars);
    array<unsigned char>^ a = gcnew array<unsigned char>(len);
    int i=0;

    while(i<len){
        a[i] = chars[i];
        i++;
    }
    return Encoding::UTF8->GetString(a);

}

String^ getTemplet(array<Byte>^ byte,const char* p){

    return TempSample::TempletExtractorSample::getTemplate(byte,toString(p));

}


JNIEXPORT jstring JNICALL Java_test5_TempletGenerator_getTemplate
    (JNIEnv *env, jobject c, jbyteArray imageArray, jstring name){

        jbyte* bufferPtr = env->GetByteArrayElements(imageArray, NULL);
        jboolean isCopyName;
        const char *nm = env->GetStringUTFChars(name,&isCopyName);

        return getTemplet(bufferPtr, nm);
}

VC++ code is showing a compilation error in the JNI Code

TempletGen.cpp(39): error C2664: 'getTemplet' : cannot convert parameter 1 from 'jbyte *' to 'cli::array ^'

Please help to convert JNI byte array (jbyte) to array so that i can all c#function?


Solution

  • It appears that you have more than one issue in your code (i.e. getTemplet returns a String^ which you attempt to return as a jstring from the Java_test5_TempletGenerator_getTemplate method).

    Regarding your specific question: how do I convert the imageArray to something that can be used as parameter 1 in the call to the getTemplet method, you can do the following:

    int len = env->GetArrayLength(imageArray);
    unsigned char* bufferPtr = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(imageArray, NULL));
    array<Byte>^ byteArray = gcnew array<Byte>(len);
    Marshal::Copy((IntPtr)bufferPtr, byteArray, 0, len);
    

    Now you can use byteArray as parameter 1 in the call to getTemplet.