使用JNA从Java调用C ++ dll方法并避免使用方法名称Mangling

时间:2013-04-12 07:33:26

标签: c++ jna

我一直在浏览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端向我提供解决方案,请提供示例代码:)

2 个答案:

答案 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,你应该能够将它构建为一个版本而不是调试来修复函数名称,如果你还没有这样做的话。