我一直在通过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加载。

09-12 04:19