我有一个调用C dll的c#程序,后者又调用java dll(使用jet excelsior构建第三方程序)。我将一个xml字符串从c#传递到java中,然后java将字符串返回到c#进行处理。
这适用于第一次迭代,但是在第二次迭代时我得到以下异常......
尝试读取或写入受保护的内存。这通常是一个 表明其他内存已损坏。
以下是我将其列为相关代码的内容,但如果您需要其他任何内容,请告知我们。
C#调用C dll
public static class DllCall
{
[DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)]
public static extern int initDll([MarshalAs(UnmanagedType.LPStr)] string userDllName);
[DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)]
public static extern void finalizeDll();
[DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 newClassInstance(String rootPath, String cfgPath, String logPath );
[DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)]
public static extern String request(UInt32 hClassInst, [MarshalAs(UnmanagedType.LPStr)] String input);
[DllImport("Stubs", CallingConvention = CallingConvention.Cdecl)]
public static extern void close();
}
C dll中抛出错误的方法
const char* request(jobject obj, char* input )
{
jstring inputString;
jstring outputString;
const char *nativeString;
jmethodID mID = (*env)->GetMethodID (env, jClass, "request", "(Ljava/lang/String;)Ljava/lang/String;");
if (!mID){
printf("\nError: dllClass.request() not found\n");
return 0;
}
inputString = (*env)->NewStringUTF(env, input);
outputString = (*env)->CallObjectMethod(env, obj, mID, inputString);
nativeString = (*env)->GetStringUTFChars(env, outputString, 0);
return nativeString;
}
这里要求的是实际导致异常的C#代码。
public string request(string xmlInput)
{
LogManager.logMessage("Sending request to Java. Request is - " + xmlInput);
string rs ="";
Console.Write("Making request");
//this works fine
rs = DllCall.request(hClass, xmlInput);
Console.Write("---> request() rs = {0}\n", rs);
// this throws the error
rs = DllCall.request(hClass, "<?xml version='1.0' encoding='utf-8'?><moo><request name=\"Panel.Open.GetSelectionTemplate\"/></moo>");
return rs;
}
在回应丹尼尔时,这里宣布了env
#include <jni.h>
#include <windows.h>
JNIEnv *env;
JavaVM *jvm;
HANDLE hUserDll;
jclass jClass;
char* dllname;
这是如何初始化的。
int initDll(char* userDllName)
{
jClass = NULL;
hUserDll = loadDll(userDllName);
dllname = userDllName;
initJavaRT(hUserDll, &jvm, &env);
jClass = lookForClass(env, "XActMain/XActGeminiX3/XActGeminiX3IFX");
return jClass ? 1 : 0;
}
/*
* Initialize JET run-time.
*/
void initJavaRT(HANDLE myDllHandle, JavaVM** pjvm, JNIEnv** penv)
{
int result;
JavaVMInitArgs args;
JNI_GetDefaultJavaVMInitArgs_func =
(jint (JNICALL *) (void *args))
GetProcAddress (myDllHandle, "JNI_GetDefaultJavaVMInitArgs");
JNI_CreateJavaVM_func =
(jint (JNICALL *) (JavaVM **pvm, void **penv, void *args))
GetProcAddress (myDllHandle, "JNI_CreateJavaVM");
if(!JNI_GetDefaultJavaVMInitArgs_func) {
printf ("%s doesn't contain public JNI_GetDefaultJavaVMInitArgs\n", dllname);
exit (1);
}
if(!JNI_CreateJavaVM_func) {
printf ("%s doesn't contain public JNI_CreateJavaVM\n", dllname);
exit (1);
}
memset (&args, 0, sizeof(args));
args.version = JNI_VERSION_1_2;
result = JNI_GetDefaultJavaVMInitArgs_func(&args);
if (result != JNI_OK) {
printf ("JNI_GetDefaultJavaVMInitArgs() failed with result %d\n", result);
exit(1);
}
/*
* NOTE: no JVM is actually created
* this call to JNI_CreateJavaVM is intended for JET RT initialization
*/
result = JNI_CreateJavaVM_func (pjvm, (void **)penv, &args);
if (result != JNI_OK) {
printf ("JNI_CreateJavaVM() failed with result %d\n", result);
exit(1);
}
printf ("JET RT initialized\n");
fflush (stdout);
}
这是对Joes关于初始化的评论......
public class Test
{
public UInt32 hClass;
public Test()
{
initDll();
newClassInstance(rootConfig, config, logFile);
}
........
public void newClassInstance(string rootPath, string cfgPath, string logPath)
{
hClass = DllCall.newClassInstance(rootPath, cfgPath, logPath);
Console.Write("---> hClass = {0}\n", hClass);
}
public void initDll()
{
int rc = DllCall.initDll("dllClass.dll");
Console.Write("---> initDll() rc = {0}\n", rc);
}
汉斯指出了以下链接potential answer
但我不知道如何修改我当前的代码以适应此解决方案。
正如我所说的,它会工作一次然后在第二次迭代时崩溃。
答案 0 :(得分:1)
我不确定它为什么第一次工作,但你将一个类对象(hClass
)传递给request
而不是该类的实例。
rs = DllCall.request(hClass, xmlInput); //The error is thrown on this line
看看这是否解决了问题:
public string request(string xmlInput)
{
LogManager.logMessage("Sending request to Java. Request is - " + xmlInput);
string rs ="";
Console.Write("Making request");
UInt32 hClassInst = DllCall.newClassInstance(rootPath, cfgPath, logPath); // <-- New line, using your own rootPath, cfgPath, logPath variables
rs = DllCall.request(hClassInst, xmlInput); // <-- Modified line, using hClassInst instead of hClass
Console.Write("---> request() rs = {0}\n", rs);
return rs;
}
如果这样可以解决问题,那么您应该重构它并将newClassInstance
调用拉出到先前的初始化方法。