如何用 JNA 正确调用这个 DLL? EXCEPTION_ACCESS_VIOLATION
How to properly call this DLL with JNA? EXCEPTION_ACCESS_VIOLATION
我正在尝试使用 Java 和来自 Windows 的 JNA 访问 C DLL 的方法。
有时一切顺利,但有时我会得到一个 EXCEPTION_ACCESS_VIOLATION(它似乎是随机的,当它工作时,当它不工作时,更多关于这个在底部)。我已经阅读了一些关于此异常的主题,但没有成功。
这是DLL中导出的部分:
#ifdef __WIN32__
extern "C"{
__declspec (dllexport) int __stdcall SpellInit(const char *path_dic, const char *path_volg);
__declspec (dllexport) int __stdcall SpellTerminate(void **lista);
__declspec (dllexport) LPSTR __stdcall SpellSuggestChar(const unsigned char *palabra);
__declspec (dllexport) LPSTR SpellGetUdr(void);
__declspec (dllexport) int SpellSetOptions(int option);
}
这是他们装饰(或不装饰)的方式:
SpellInit
SpellTerminate
SpellSuggestChar
_SpellGetUdr@0
_SpellSetOptions@4
Dependency Walker 在我打开它时抛出这两个错误:
错误:由于隐式依赖模块中缺少导出函数,至少有一个模块具有未解析的导入。
错误:找到具有不同 CPU 类型的模块。
但是这个 DLL 派生自另一个运行良好的 DLL(虽然它是从 VB 代码调用的)并且也会抛出相同的两个错误。
最后我是这样称呼它的:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
import java.util.HashMap;
public class Test_DLL {
public interface ORTCLI extends StdCallLibrary {
ORTCLI INSTANCE = (ORTCLI) Native.loadLibrary("ORTCLI", ORTCLI.class, new HashMap(){{
put("SpellGetUdr","_SpellGetUdr@0");
put("SpellSetOptions","_SpellSetOptions@4");
}});
int SpellInit(String path_dic, String path_volg);
String SpellSuggestChar(String pal);
int SpellAddUdr(String pal);
String SpellGetUdr();
int SpellTerminate();
}
我也尝试过扩展 Library 而不是 StdCallLibrary(我想 StdCallLibrary 应该是最好的选择,不是吗?),但结果是一样的:调用 SpellSuggestChar 或 SpellGetUdr 时崩溃。这两个函数的共同点是都需要从sqlite数据库中读写。
无论如何,它不会总是崩溃,而且它取决于 computer/user 执行它。例如,如果从域计算机中的管理员帐户执行,它崩溃的频率低于在非特权帐户中执行的情况。
我知道有很多可能的错误原因,但现在我只想知道你们中的一些人是否可以在 DLL 导出或 JNA 代码中发现错误(第一次使用它),所以我可以排除一些可能性。
谢谢。
Technomage 说得对,他说所有方法都应该声明为使用 stdcall,而不是混合使用和不使用 stdcall 的方法。但这只是问题的一半。
最终解决方案来自更改 SQLite 编译选项,特别是 -DTHREADSAFE 参数。激活后一切正常。
干杯。
我正在尝试使用 Java 和来自 Windows 的 JNA 访问 C DLL 的方法。
有时一切顺利,但有时我会得到一个 EXCEPTION_ACCESS_VIOLATION(它似乎是随机的,当它工作时,当它不工作时,更多关于这个在底部)。我已经阅读了一些关于此异常的主题,但没有成功。
这是DLL中导出的部分:
#ifdef __WIN32__
extern "C"{
__declspec (dllexport) int __stdcall SpellInit(const char *path_dic, const char *path_volg);
__declspec (dllexport) int __stdcall SpellTerminate(void **lista);
__declspec (dllexport) LPSTR __stdcall SpellSuggestChar(const unsigned char *palabra);
__declspec (dllexport) LPSTR SpellGetUdr(void);
__declspec (dllexport) int SpellSetOptions(int option);
}
这是他们装饰(或不装饰)的方式:
SpellInit
SpellTerminate
SpellSuggestChar
_SpellGetUdr@0
_SpellSetOptions@4
Dependency Walker 在我打开它时抛出这两个错误:
错误:由于隐式依赖模块中缺少导出函数,至少有一个模块具有未解析的导入。 错误:找到具有不同 CPU 类型的模块。
但是这个 DLL 派生自另一个运行良好的 DLL(虽然它是从 VB 代码调用的)并且也会抛出相同的两个错误。
最后我是这样称呼它的:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
import java.util.HashMap;
public class Test_DLL {
public interface ORTCLI extends StdCallLibrary {
ORTCLI INSTANCE = (ORTCLI) Native.loadLibrary("ORTCLI", ORTCLI.class, new HashMap(){{
put("SpellGetUdr","_SpellGetUdr@0");
put("SpellSetOptions","_SpellSetOptions@4");
}});
int SpellInit(String path_dic, String path_volg);
String SpellSuggestChar(String pal);
int SpellAddUdr(String pal);
String SpellGetUdr();
int SpellTerminate();
}
我也尝试过扩展 Library 而不是 StdCallLibrary(我想 StdCallLibrary 应该是最好的选择,不是吗?),但结果是一样的:调用 SpellSuggestChar 或 SpellGetUdr 时崩溃。这两个函数的共同点是都需要从sqlite数据库中读写。
无论如何,它不会总是崩溃,而且它取决于 computer/user 执行它。例如,如果从域计算机中的管理员帐户执行,它崩溃的频率低于在非特权帐户中执行的情况。
我知道有很多可能的错误原因,但现在我只想知道你们中的一些人是否可以在 DLL 导出或 JNA 代码中发现错误(第一次使用它),所以我可以排除一些可能性。
谢谢。
Technomage 说得对,他说所有方法都应该声明为使用 stdcall,而不是混合使用和不使用 stdcall 的方法。但这只是问题的一半。
最终解决方案来自更改 SQLite 编译选项,特别是 -DTHREADSAFE 参数。激活后一切正常。
干杯。