I'm trying to return a string from C function to a C# program and I'm getting a AccessViolationException and I have no idea why? Here's my C code:
__declspec(dllexport) void DoLuceneRequest(byte *xmlin, int datasize, char *xmlout){
JNIEnv *env;
if (jvm == NULL){
JavaVMOption* options = new JavaVMOption[1];
JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
options[0].optionString = "-Djava.class.path=LuceneServlet.jar;lucene-core-2.9.4.jar;lucene-spellchecker-2.9.4.jar;servlet-api.jar";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
JNI_CreateJavaVM(&jvm, (void**)&globalenv, &vm_args);
delete options;
}
jvm->AttachCurrentThread((void **)&env, NULL);
jobject obj;
jclass cls = env->FindClass("lucene/LuceneServlet");
if (cls != NULL){
jmethodID constructor = env->GetMethodID(cls, "<init>", "()V");
if (constructor != NULL){
obj = env->NewObject(cls, constructor);
if (obj != NULL){
jmethodID processRequest = env->GetMethodID(cls, "processRequest", "([B)Ljava/lang/String;");
if (processRequest != NULL){
jbyte *jbytes = (jbyte*) xmlin;
jbyteArray jba = env->NewByteArray(datasize);
env->SetByteArrayRegion(jba, 0, datasize, jbytes);
jstring results = (jstring)env->CallObjectMethod(obj, processRequest, jba);
MessageBox(NULL, "call successful, returning values", "", MB_OK);
const char *cresults = env->GetStringUTFChars(results, NULL);
strcpy_s(xmlout, strlen(cresults) + 1, cresults);
for (int i=0; i <= strlen(cresults); i++){
if (cresults[i] == '\0'){
MessageBox(NULL, "Has null terminator", "", MB_OK);
}
}
MessageBox(NULL, cresults, "", MB_OK);
MessageBox(NULL, xmlout, "", MB_OK);
env->ReleaseStringUTFChars(results, cresults);
//env->ReleaseByteArrayElements(jba, jbytes, 0);
}else{
MessageBox(NULL, "method not found", "", MB_OK);
}
}
}
}
//jvm->DestroyJavaVM();
jvm->DetachCurrentThread();
}
The messagebox's show the correct string.
And here's my C# code:
[DllImport("LuceneHandler.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DoLuceneRequest(byte[] xmlin, int datasize, StringBuilder xmlout);
StringBuilder sbRsltXml = new StringBuilder();
//DisplayHelloFromDLL("hello", sbRsltXml);
//MessageBox.Show(sbRsltXml.ToString());
byte[] ubytes = Encoding.UTF8.GetBytes("<test></test>");
DoLuceneRequest(ubytes, ubytes.Length, sbRsltXml);
MessageBox.Show(sbRsltXml.ToString());
If I do new StringBuilder(99999) then it works, but I don't know the size of the returned data ahead of time so I don't want to do that. Any ideas on what I'm doing wrong?