TLD
TLD

Reputation: 8135

Convert String types when using java jni

I try to call C# code from java application, and this is done through a C++ library. So basically I end up in 03 different types of String:

The problem is I have to convert among them. So my convert codes are:
From C++ to C#

String^ toStringCS(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);
}

From C# to C++

char* toStringCPP(String^ P){
   pin_ptr<const wchar_t> wch = PtrToStringChars(P);
   printf_s("%S\n", wch);
   size_t convertedChars = 0;
   size_t  sizeInBytes = ((P->Length + 1) * 2);
   errno_t err = 0;
   char *ch = (char *)malloc(sizeInBytes);
   return ch;
}

From jstring to C++

jboolean isCopyS1;
const char *c_S1 = env->GetStringUTFChars(s1, &isCopyS1);

But I got error while trying to execute the application. When I disabled the toStringCS method, the program runs normally. Can someone show me what did I do wrong in that method?
And I googled to convert from String^ to jstring but I coudln't find any solution.. Can you suggest me some ways to do it ?
Thank you very much.

Upvotes: 1

Views: 1070

Answers (1)

Tom Blodget
Tom Blodget

Reputation: 20812

I'm not sure where you are going wrong. You are missing free, at the least. But I wouldn't go through char * and certainly not modified UTF-8 (via GetStringUTFChars).

.NET System::String and Java System.String on Windows are both code-unit-counted, sequences of UTF-16LE-encoded Unicode characters.

#include <vcclr.h>

jstring CopyDotNetString(JNIEnv *env, System::String^ value)
{
    if (value == nullptr) return 0;

    const auto codeunitCount = value->Length;
    /* .NET System::Char, C++ std::wchar_t, JNI jchar, and Java char are 
        all the same size and hold a UTF-16LE code unit. */
    const pin_ptr<const wchar_t> buffer = PtrToStringChars(value); 
    return env->NewString(
        reinterpret_cast<const jchar*>(buffer),
        codeunitCount);
}

System::String^ GetStringFromJava(JNIEnv *env, jstring value)
{
    if (value == 0) return nullptr;

    const auto codeunitCount = env->GetStringLength(value);
    const auto buffer = env->GetStringChars(value, NULL);
    try {
        return gcnew System::String(
           reinterpret_cast<const wchar_t*>(buffer), 
           0, 
           codeunitCount);
    }
    finally {
        env->ReleaseStringChars(value, buffer);
    }
}

Upvotes: 3

Related Questions