java.lang.UnsatisfiedLinkError: The specified procedure could not be found
java.lang.UnsatisfiedLinkError: The specified procedure could not be found
我正在尝试开发 C++ DLL 的 JNA 包装器。
我无权访问 DLL 的代码。我使用 depends.exe 检查了 DLL,发现 C++ 方法周围没有装饰器。而且我检索到的C++ *.h文件中似乎也设置了extern "C"
。
但是我有以下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'compute': The specified procedure could not be found.
at com.sun.jna.Function.(Function.java:252)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:600)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:576)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:562)
at com.sun.jna.Library$Handler.invoke(Library.java:243)
at com.sun.proxy.$Proxy0.compute(Unknown Source)
at com.JNA.main(JNA.java:171)
查看我的 cpp *.h 文件:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct s_mine
{
e_color color; //e_color is enum type made of int values
his data;
int str;
unsigned int wild;
unsigned int hello;
float rice;
} mine;
typedef struct s_his
{
unsigned char * data;
unsigned int size;
} his;
// compute function which raised the exception
int compute(const his* const input, void ** outputPointer);
// treat function raised also the same exception
int treat(const mine* inputParameter, mine* outputParameter);
#ifdef __cplusplus
}
#endif
见下面我的 JNA 包装器:
public interface MyInterface extends Library {
@FieldOrder({"data", "size"})
public static class his extends Structure {
public static class ByReference extends his implements Structure.ByReference {}
public static class ByValue extends rt_buffer implements Structure.ByValue {}
public Pointer data;
public int size;
}
@FieldOrder({"color","data","str","wild","hello","rice"})
public class mine extends Structure {
public static class ByReference extends mine implements Structure.ByReference {}
public int color;
public his data;
public int str;
public int wild;
public int hello;
public float rice;
}
public int compute(his input, Pointer[] outputPointer);
public int treat(mine inputParameter, mine outputParameter);
}
因此在我的测试中class我设置:
// COMPUTE
MyInterface.his.ByReference input_ref = new MyInterface.his.ByReference();
ByteBuffer init_buffer;
// init_buffer is initialized with some not null values
Pointer init_p = Native.getDirectBufferPointer(init_buffer);
input_ref.data = init_p;
input_ref.size = init_buffer.capacity();
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
// TREAT
MyInterface.mine.ByReference inputParameter_ref = new MyInterface.mine.ByReference();
MyInterface.his.ByValue buffer = new MyInterface.his.ByValue();
// initialize buffer with an input buffer value different from null value
// Set other fields of inputParameter_ref with none null values
inputParameter_ref.data = buffer;
MyInterface.mine.ByReference outputParameter_ref = null;
int resultTreat = treat(inputParameter_ref, outputParameter_ref);
因此我感觉引发的异常不是来自我的实现而是来自DLL。但是我没有任何线索来解释为什么我在 post.
开头的断言
除了装饰器和外部声明问题,还有其他原因吗?
如何使用 depends.exe 检查 DLL 检查是否设置了外部声明?
@dbwiddis 感谢您的回复,但是:
const his* const input 表示input是常量his结构上的常量指针。
这意味着指针是只读值的只读参数。
我把outputPointer设置为一个数组,因为我不确定如何使用它。
事实上,我需要它作为另一种方法的输入参数。对于 C++,我有类似的东西:
int compute(const his* const input, void ** outputPointer); // **outputPointer is an output of compute method
int manage(void * inputPointer); // As *outputPointer becomes an input of manage method
因此我的 jna Wrapper 中有:
public int compute(his input, Pointer[] outputPointer);
public int manage(Pointer inputPointer);
在我的测试中 class 我有 :
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
int manage(outputPointer[0]);
无论如何,我也试过你的建议如下:
因此我在我的 jna Wrapper 中有:
public int compute(his input, PointerByReference outputPointer);
public int manage(Pointer inputPointer);
在我的测试中 class 我有 :
PointerByReference outputPointer = null;
int resultCompute = myInterface.compute(input_ref, outputPointer);
int myInterface.manage(outputPointer.getValue());
但我仍然遇到同样的问题。
作为提醒,无论 c++ dll 中定义的方法是什么,我都会遇到相同的引发异常。
我真的觉得这个问题不是来自我的 jna 实现。
同样重要的细节,在我的测试中 class 我执行了 dll 的上传:
Map options = new HashMap();
options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() {
public String getFunctionName(NativeLibrary library, Method method) {
System.out.println("method names = "+method.getName());
return super.getFunctionName(library, method);
}
});
MyInterface myInterface = (MyInterface) Native.load("dllName",MyInterface.class,options);
上面的 sysout 显示了当前调用的方法的名称,即我显示了 method names = compute
。
调试代码,我注意到它们是方法名称的问题。
但是当 sysout 显示我在我的 jna 包装器中声明的方法的名称时,它没有帮助。
我刚刚使用 c++ dll 中未定义的伪造方法进行了快速测试,我遇到了同样的错误:
找不到该程序。因此,我真的认为该 dll 存在问题,但我不知道如何找出它...
最后,我不得不在我的 java Test main class 中添加以下行来调用我的包装器来解决我的问题:
System.setProperty("jna.library.path", "C:\myWrapper\src\main\resources");
其中C:\myWrapper\src\main\resources是存放我的dll文件的文件夹。
但它没有解释为什么我不需要为存储在同一文件夹中的其他 dll 设置此行,因为我也在我的环境变量中声明 jna.library.path。
我正在尝试开发 C++ DLL 的 JNA 包装器。
我无权访问 DLL 的代码。我使用 depends.exe 检查了 DLL,发现 C++ 方法周围没有装饰器。而且我检索到的C++ *.h文件中似乎也设置了extern "C"
。
但是我有以下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'compute': The specified procedure could not be found.
at com.sun.jna.Function.(Function.java:252) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:600) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:576) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:562) at com.sun.jna.Library$Handler.invoke(Library.java:243) at com.sun.proxy.$Proxy0.compute(Unknown Source) at com.JNA.main(JNA.java:171)
查看我的 cpp *.h 文件:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct s_mine
{
e_color color; //e_color is enum type made of int values
his data;
int str;
unsigned int wild;
unsigned int hello;
float rice;
} mine;
typedef struct s_his
{
unsigned char * data;
unsigned int size;
} his;
// compute function which raised the exception
int compute(const his* const input, void ** outputPointer);
// treat function raised also the same exception
int treat(const mine* inputParameter, mine* outputParameter);
#ifdef __cplusplus
}
#endif
见下面我的 JNA 包装器:
public interface MyInterface extends Library {
@FieldOrder({"data", "size"})
public static class his extends Structure {
public static class ByReference extends his implements Structure.ByReference {}
public static class ByValue extends rt_buffer implements Structure.ByValue {}
public Pointer data;
public int size;
}
@FieldOrder({"color","data","str","wild","hello","rice"})
public class mine extends Structure {
public static class ByReference extends mine implements Structure.ByReference {}
public int color;
public his data;
public int str;
public int wild;
public int hello;
public float rice;
}
public int compute(his input, Pointer[] outputPointer);
public int treat(mine inputParameter, mine outputParameter);
}
因此在我的测试中class我设置:
// COMPUTE
MyInterface.his.ByReference input_ref = new MyInterface.his.ByReference();
ByteBuffer init_buffer;
// init_buffer is initialized with some not null values
Pointer init_p = Native.getDirectBufferPointer(init_buffer);
input_ref.data = init_p;
input_ref.size = init_buffer.capacity();
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
// TREAT
MyInterface.mine.ByReference inputParameter_ref = new MyInterface.mine.ByReference();
MyInterface.his.ByValue buffer = new MyInterface.his.ByValue();
// initialize buffer with an input buffer value different from null value
// Set other fields of inputParameter_ref with none null values
inputParameter_ref.data = buffer;
MyInterface.mine.ByReference outputParameter_ref = null;
int resultTreat = treat(inputParameter_ref, outputParameter_ref);
因此我感觉引发的异常不是来自我的实现而是来自DLL。但是我没有任何线索来解释为什么我在 post.
开头的断言除了装饰器和外部声明问题,还有其他原因吗?
如何使用 depends.exe 检查 DLL 检查是否设置了外部声明?
@dbwiddis 感谢您的回复,但是:
const his* const input 表示input是常量his结构上的常量指针。 这意味着指针是只读值的只读参数。
我把outputPointer设置为一个数组,因为我不确定如何使用它。 事实上,我需要它作为另一种方法的输入参数。对于 C++,我有类似的东西:
int compute(const his* const input, void ** outputPointer); // **outputPointer is an output of compute method
int manage(void * inputPointer); // As *outputPointer becomes an input of manage method
因此我的 jna Wrapper 中有:
public int compute(his input, Pointer[] outputPointer);
public int manage(Pointer inputPointer);
在我的测试中 class 我有 :
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
int manage(outputPointer[0]);
无论如何,我也试过你的建议如下: 因此我在我的 jna Wrapper 中有:
public int compute(his input, PointerByReference outputPointer);
public int manage(Pointer inputPointer);
在我的测试中 class 我有 :
PointerByReference outputPointer = null;
int resultCompute = myInterface.compute(input_ref, outputPointer);
int myInterface.manage(outputPointer.getValue());
但我仍然遇到同样的问题。 作为提醒,无论 c++ dll 中定义的方法是什么,我都会遇到相同的引发异常。 我真的觉得这个问题不是来自我的 jna 实现。 同样重要的细节,在我的测试中 class 我执行了 dll 的上传:
Map options = new HashMap();
options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() {
public String getFunctionName(NativeLibrary library, Method method) {
System.out.println("method names = "+method.getName());
return super.getFunctionName(library, method);
}
});
MyInterface myInterface = (MyInterface) Native.load("dllName",MyInterface.class,options);
上面的 sysout 显示了当前调用的方法的名称,即我显示了 method names = compute
。
调试代码,我注意到它们是方法名称的问题。
但是当 sysout 显示我在我的 jna 包装器中声明的方法的名称时,它没有帮助。
我刚刚使用 c++ dll 中未定义的伪造方法进行了快速测试,我遇到了同样的错误:
找不到该程序。因此,我真的认为该 dll 存在问题,但我不知道如何找出它...
最后,我不得不在我的 java Test main class 中添加以下行来调用我的包装器来解决我的问题: System.setProperty("jna.library.path", "C:\myWrapper\src\main\resources"); 其中C:\myWrapper\src\main\resources是存放我的dll文件的文件夹。
但它没有解释为什么我不需要为存储在同一文件夹中的其他 dll 设置此行,因为我也在我的环境变量中声明 jna.library.path。