1

I'm using C++/CLI to connect a Java client to my C# ServiceHost. So far I have used this to access my service, where Client defines my ServiceHost client:

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;
}


That works fine, but I want to be able to store my Client object on the Java side in order to make calls with the same object instead of opening and closing the connection for each call.

It has been difficult to find anything definitive about this. Is it possible?



Here is the solution I came up with per the marked answer:

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;
}

By storing that long in Java, I can pass it as a jlong parameter to my GetData method:

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;
}

All I have left to do is create another JNI method to close the Client connection and dispose the object.

4

1 回答 1

1

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

创建第二个用于清理内存的本机方法,该方法接受来自上一次调用的 store jlong​​,将其转换回客户端指针,然后将其删除。

有关句柄到指针转换的正确语法,请参见此答案

于 2013-11-14T20:49:25.677 回答