我一直在通过StackOverflow上的链接来了解如何解决方法名称修饰的问题,但没有找到带有实时示例的解决方案。
方案-客户端提供了一个C ++ Ex.dll文件。我需要访问Ex.dll并通过Java在相同的方法中调用方法。
限制-无法修改Ex.dll,我只能访问相同的文件。
面临的问题-通过JNA访问Ex.dll时遇到以下异常
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'getCPUSpeed': The specified procedure could not be found.
at com.sun.jna.Function.<init>(Function.java:134)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:336)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:316)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at $Proxy0.getCPUSpeed(Unknown Source)
at cpp.java.JnaTest.main(JnaTest.java:16)
Google搜索了很多,发现它是由于方法名Mangling引起的,但是再一次在解决方案中找不到任何好的示例代码。
这是我使用的代码-
import com.sun.jna.Native;
class JnaTest
{
public static void main(String args[])
{
try
{
JnaInterface jInterface = (JnaInterface) Native.loadLibrary("Ex", JnaInterface.class);
System.out.println("Calling C++ DLL method");
System.out.println("========================");
System.out.println("getCPUSpeed() -- "+jInterface.getCPUSpeed());
} catch (Exception e) {
e.printStackTrace();
}
}
}
package cpp.java;
import com.sun.jna.Library;
public interface JnaInterface extends Library{
public int getCPUSpeed();
}
更新1:******************************************
下面提到的是当我通过依赖行者浏览DBMM.dll时获得的实际功能
DBMM DLL函数-
0cDbmmInterfaceCache @@ QAE @ ABV0 @@ Z
0cDbmmInterfaceCache @@ QAE @ XZ
0cDbmmInterfaceControl @@ QAE @ ABV0 @@ Z
0cDbmmInterfaceControl @@ QAE @ XZ
0cDbmmInterfaceEcon @@ QAE @ ABV0 @@ Z
0cDbmmInterfaceEcon @@ QAE @ XZ
0cDbmmInterfaceKnob @@ QAE @ XZ
0cDbmmInterfaceOutput @@ QAE @ ABV0 @@ Z
0cDbmmInterfaceOutput @@ QAE @ H @ Z
0cDbmmInterfacePoolLoan @@ QAE @ ABV0 @@ Z
0cDbmmInterfacePoolLoan @@ QAE @ V?$ basic_string @ DU?$ char_traits @ D @ std @@ V?$ allocator @ D @ 2 @@ std @@@ Z
0cDbmmMacroEcon @@ QAE @ ABV0 @@ Z
0cDbmmMacroEcon @@ QAE @ ABVcDbmmInterfaceEcon @@ __ N @ Z
0cDbmmMtgBasisConstSpreadModel @@ IAE @ XZ
0cDbmmMtgBasisConstSpreadModel @@ QAE @ ABV0 @@ Z
0cDbmmMtgBasisConstSpreadModel @@ QAE @ PBD @ Z
0cDbmmMtgBasisModel @@ QAE @ ABV0 @@ Z
0cDbmmMtgBasisModel @@ QAE @ XZ
0cScaleFieldsSubSum @@ QAE @ NN @ Z
1cDbmmInterfaceCache @@ QAE @ XZ
1cDbmmInterfaceControl @@ QAE @ XZ
1cDbmmInterfaceEcon @@ QAE @ XZ
1cDbmmInterfaceKnob @@ QAE @ XZ
1cDbmmInterfaceOutput @@ QAE @ XZ
1cDbmmInterfacePoolLoan @@ QAE @ XZ
1cDbmmMacroEcon @@ QAE @ XZ
1cDbmmMtgBasisConstSpreadModel @@ UAE @ XZ
1cDbmmMtgBasisModel @@ UAE @ XZ
1cScaleFieldsSubSum @@ QAE @ XZ
4cDbmmInterface @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfaceCache @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfaceControl @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfaceEcon @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfaceKnob @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfaceOutput @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmInterfacePoolLoan @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmMacroEcon @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmMtgBasisConstSpreadModel @@ QAEAAV0 @ ABV0 @@ Z
4cDbmmMtgBasisModel @@ QAEAAV0 @ ABV0 @@ Z
4cScaleFieldsSubSum @@ QAEAAV0 @ ABV0 @@ Z
_7cDbmmMtgBasisConstSpreadModel @@ 6B @
_7cDbmmMtgBasisModel @@ 6B @
_FcDbmmInterfaceOutput @@ QAEXXZ
_FcDbmmInterfacePoolLoan @@ QAEXXZ
_FcScaleFieldsSubSum @@ QAEXXZ
?Add @ cScaleFieldsSubSum @@ QAEXNN @ Z
?InitSubsum @ cScaleFieldsSubSum @@ QAEXNN @ Z
ReInit @ cDbmmMacroEcon @@ QAEX_N @ Z
不知道如何通过Java调用这些函数。
感谢有人可以从Java端为我提供解决方案,请提供示例代码:)
最佳答案
您的函数使用JNI和stdcall约定修饰;它不是C ++编写的。
给定Java_sysInfo_
前缀,该库看起来像是JNI库。如果是这种情况,则只需声明等效的Java端,例如
// default package
public class sysInfo {
static { System.loadLibrary("Ex"); }
public static native int getCPUSpeed();
}
我认为您可能会发现此映射是正确的映射,并且您不需要JNA。
编辑
给定具有任意ctor输入参数和方法
getCount()
的C ++类:extern "C" int getCountForName(const char* name) {
MyCPPClass mycpp(name);
return mycpp.getCount();
}
Compile that into a shared library,并通过JNA加载。