如何使用JNI将C ++ / CLI对象返回给Java?

时间:2013-11-14 20:07:16

标签: java java-native-interface c++-cli

我正在使用C ++ / CLI将Java客户端连接到我的C#ServiceHost。到目前为止,我已使用它来访问我的服务,其中Client定义了我的ServiceHost客户端:

JNIEXPORT jstring JNICALL Java_Client_GetData(JNIEnv *env, jobject, jstring xml)
{
    try
    {
        Client ^client = gcnew Client();

        return env->NewStringUTF(marshal_as<string>(
              client->GetData(marshal_as<String^>(env->GetStringUTFChars(xml, 0))
        )).c_str());
    }
    catch(Exception^ ex)
    {
        Console::WriteLine(ex->ToString());
    }
    return NULL;
}


这很好,但我希望能够将我的Client对象存储在Java端,以便使用相同的对象进行调用,而不是为每个调用打开和关闭连接。

很难找到关于此的确定性。有可能吗?



这是我根据标记答案提出的解决方案:

JNIEXPORT jlong JNICALL Java_Client_Create(JNIEnv* env, jobject obj)
{
    try
    {
        Client^ client = gcnew Client();
        client->Connect();
        long result =  reinterpret_cast<long>(GCHandle::ToIntPtr(GCHandle::Alloc(client)).ToPointer());
        return result;
    }
    catch(Exception^ ex)
    {
        Console::WriteLine(ex->ToString());
    }
    return NULL;
}

通过在Java中存储那么久,我可以将它作为jlong参数传递给我的GetData方法:

JNIEXPORT jstring JNICALL Java_Client_GetData(JNIEnv *env, jobject, jlong ptr, jstring xml)
{
    try
    {
        GCHandle h = GCHandle::FromIntPtr(IntPtr(reinterpret_cast<void*>(ptr)));
        Client^ client = safe_cast<Client^>(h.Target);

        const char* xmlChars = (const char*)env->GetStringChars(xml, 0);
        string xmlString(xmlChars);
        env->ReleaseStringChars(xml, (const jchar*)xmlChars);

        const char* data = marshal_as<string>(client->GetData(
                marshal_as<String^>(xmlString)
            )).c_str();

        int length = strlen(data);

        return env->NewString((const jchar*)data, length);
    }
    catch(EndpointNotFoundException^)
    {
        return NULL;
    }
    catch(Exception^ ex)
    {
        Console::WriteLine(ex->ToString());
    }
    return NULL;
}

我要做的就是创建另一个JNI方法来关闭Client连接并处理该对象。

1 个答案:

答案 0 :(得分:1)

更改本机方法以返回jlong​​,并返回新创建的Client对象指针的地址。

创建第二个清理内存的本机方法,该方法接受上一次调用时的商店jlong​​,将其强制转换为Client指针,然后将其删除。

请参阅This answer for the correct syntax on handle to pointer conversion