从 Java 调用C++函数。映射"const char*"
Calling a C++ function from Java. Mapping "const char*"
我已经通过stackoverflow和Internet搜索了这一点,但尚未找到答案。
我有一个我没有源代码的指纹读取器的SDK,这意味着我无法更改它。
它有一些我需要访问的方法,我将在下面列出哪个接口(来自rs_api.h):
REALSCANSDK_API int __stdcall RS_InitSDK( const char* configFileName, int option, int* numOfDevice );
REALSCANSDK_API int __stdcall RS_InitDevice( int deviceIndex, int*deviceHandle );
REALSCANSDK_API int __stdcall RS_SetCaptureMode( int deviceHandle, int captureMode, int captureOption, bool withModeLED );
REALSCANSDK_API int __stdcall RS_SetViewWindow( int deviceHandle, HWND windowHandle, RECT drawRectangle, bool autoContrast );
REALSCANSDK_API int __stdcall RS_TakeImageDataEx( int deviceHandle, int timeout, int fingerIndex, bool withLED, unsigned char** imageData, int* imageWidth, int* imageHeight );
我设法将所有这些转换为Delphi,但我也想从Java应用程序访问。
我的原型就是这样:
public class Leitor {
public native int RS_InitSDK(String configFileName, int option, int numOfDevice );
public static void main(String[] args) {
Leitor leitor= new Leitor();
leitor.RS_InitSDK(null, 0, 0);
}
static
{
System.load("C:\temp\SDKSuprema\SDK\RS_SDK.dll");
}
}
负载位正常工作(我相信它意味着它可以找到DLL文件),但是当它运行本机方法时,它会引发异常:
线程中的异常" main" java.lang.unsatisfiedlinkerror:leitor.ritor.rs_initsdk(ljava/lang/lang/string; ii)i 在leitor.leitor.rs_initsk(本机方法) 在leitor.leitor.main(leitor.java:14)
如果我重命名dll,则将错误更改为"无法加载库",所以我认为问题是方法的映射。
我也找不到从Java调用参考参数来映射通行证。唯一的解决方案是将DLL更改以返回结构而不是单个结果,但这是不可能的,因为我无法更改代码。
第二个问题是将窗口句柄从SWT发送到JNI本机方法...
非常欢迎任何帮助!
您需要编写以Java对象接受参数的明确胶代码,并将其转换为现有C入口点预期的表示。JVM本身不会为您做到这一点。
阅读JNI规范以学习如何编写此胶代码。
特别是,要匹配您的Java声明,必须将JNI入口点命名为package_name_here_Leitor_RS_1InitSDK
或package_name_here_Leitor_RS_1InitSDK__Ljava_lang_String_2II
;请参阅规范第2章的"解决本地方法名称" 部分。此功能必须在Java可见的方面进行一些额外的论点。参见规格中的"本机方法参数"
在方法中,您可以将字符串作为jstring
值传递,您必须使用JVM中的GetStringUTFChars
助手函数转换为C字符串。
对于通过参考参数,您需要找到一种模拟它们对调用Java代码有意义的方法,例如通过传递一个由JNI代码分配的对象,或(快速而肮脏的)通过int[]
,其第一个元素由您的JNI代码分配。
您需要创建C/C 胶代码来实现Java方法,使用类调用Javah将创建一个标题,以声明本机标记为本机的Java方法。
。如果您不想编写C/C ,则可以使用JNA将JAVA代码映射到现有的C方法和结构。