如何使用JNA正确调用此DLL? EXCEPTION_ACCESS_VIOLATION

时间:2015-11-10 19:49:11

标签: java windows dll jna

我正在尝试使用Windows中的Java和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数据库读取和写入。

无论如何,它总是不会崩溃,而且还取决于哪台计算机/用户执行它。例如,如果从域计算机中的管理员帐户执行,则崩溃的频率低于在非特权帐户中执行的频率。

我知道错误有很多可能的原因,但是现在我只想知道你们中的一些人是否可以在DLL导出或JNA代码中发现错误(第一次使用它),所以我可以排除一些可能性。

感谢。

1 个答案:

答案 0 :(得分:0)

Technomage是正确的,他说所有方法都应该声明使用stdcall而不是混合方法与stdcall和没有。但这只是问题的一半。

最后,解决方案来自更改SQLite编译选项,特别是-DTHREADSAFE参数。激活后,一切都恢复正常。

干杯。