我一直在浏览StackOverflow上有关如何解决方法名称修改的链接,但没有找到任何具有实时示例的解决方案。
场景 - 客户端提供C ++ Ex.dll文件。我需要访问Ex.dll并通过Java调用相同的方法。
限制 - 无法修改Ex.dll,我只能访问相同的内容。
问题Faced-当我通过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)
搜索了很多,发现它的方法名称为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: * ** * ** * ** * ** < EM> * ** * ** * ** * ** * ** < EM> * ** * ** * ** * *
下面提到的是我通过依赖walker-
浏览DBMM.dll时获得的实际功能DBMM DLL函数 -
... 0cDbmmInterfaceCache @@ @ QAE @@ ABV0Ž
... 0cDbmmInterfaceCache @@ @ QAE XZ
... 0cDbmmInterfaceControl @@ @ QAE @@ ABV0Ž
... 0cDbmmInterfaceControl @@ @ QAE XZ
... 0cDbmmInterfaceEcon @@ @ QAE @@ ABV0Ž
... 0cDbmmInterfaceEcon @@ @ QAE XZ
... 0cDbmmInterfaceKnob @@ @ QAE XZ
... 0cDbmmInterfaceOutput @@ @ QAE @@ ABV0Ž
... 0cDbmmInterfaceOutput @@ QAE 3 H @ Z
... 0cDbmmInterfacePoolLoan @@ @ QAE @@ ABV0Ž
... 0cDbmmInterfacePoolLoan @@ @ QAE V'$ basic_string的@ DU?$ char_traits @ d @ @@ STD V'$分配器@ d @ @@ 2 STD @@@ Z
... 0cDbmmMacroEcon @@ @ QAE @@ ABV0Ž
... 0cDbmmMacroEcon @@ @ QAE ABVcDbmmInterfaceEcon @@ _Ñ@ Z
... 0cDbmmMtgBasisConstSpreadModel @@ @ IAE XZ
... 0cDbmmMtgBasisConstSpreadModel @@ @ QAE @@ ABV0Ž
... 0cDbmmMtgBasisConstSpreadModel @@ @ QAE PBD @ Z
... 0cDbmmMtgBasisModel @@ @ QAE @@ ABV0Ž
... 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Ž
... 4cDbmmInterfaceCache @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmInterfaceControl @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmInterfaceEcon @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmInterfaceKnob @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmInterfaceOutput @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmInterfacePoolLoan @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmMacroEcon @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmMtgBasisConstSpreadModel @@ @ QAEAAV0 @@ ABV0Ž
... 4cDbmmMtgBasisModel @@ @ QAEAAV0 @@ ABV0Ž
... 4cScaleFieldsSubSum @@ @ QAEAAV0 @@ ABV0Ž
?? _ @@ 7cDbmmMtgBasisConstSpreadModel 6B @
?? _ @@ 7cDbmmMtgBasisModel 6B @
?? _ @@ FcDbmmInterfaceOutput QAEXXZ
?? _ @@ FcDbmmInterfacePoolLoan QAEXXZ
?? _ @@ FcScaleFieldsSubSum QAEXXZ
?添加@ @@ cScaleFieldsSubSum QAEXNN @ Z
?InitSubsum @ @@ cScaleFieldsSubSum QAEXNN @ Z
?REINIT @ @@ cDbmmMacroEcon QAEX_N @ Z
不确定如何通过Java调用这些函数。
感谢有人能从Java端向我提供解决方案,请提供示例代码:)
答案 0 :(得分:0)
您的函数使用JNI和stdcall约定进行修饰;它不是C ++ - 受损。
看起来这个库是一个JNI库,给定Java_sysInfo_
前缀。如果是这种情况,则只需要声明等效的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加载。
答案 1 :(得分:0)
如果你通过Visual Studio构建DLL,你应该能够将它构建为一个版本而不是调试来修复函数名称,如果你还没有这样做的话。