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.

开头的断言
  1. 除了装饰器和外部声明问题,还有其他原因吗?

  2. 如何使用 depends.exe 检查 DLL 检查是否设置了外部声明?

@dbwiddis 感谢您的回复,但是:

  1. const his* const input 表示input是常量his结构上的常量指针。 这意味着指针是只读值的只读参数。

  2. 我把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。