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.