1

我一直在通过 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)

谷歌了很多,发现它是由于方法名称 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:* ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * *

下面提到的是我通过依赖walker浏览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端的解决方案,请提供示例代码:)

4

2 回答 2

0

如果您通过 Visual Studio 构建 DLL,您应该能够将其构建为发行版而不是调试来修复函数名称(如果您尚未这样做)。

于 2013-09-10T18:05:49.893 回答
0

您的函数使用 JNI 和 stdcall 约定进行装饰;它不是 C++ 损坏的。

Java_sysInfo_给定前缀,看起来该库是一个 JNI 库。如果是这种情况,您只需要声明等效的 Java 端,例如

// default package
public class sysInfo {
    static { System.loadLibrary("Ex"); }
    public static native int getCPUSpeed();
}

我想你可能会发现这个映射是正确的并且你不需要 JNA。

编辑

给定一个具有任意 ctor 输入参数和方法的 C++ 类getCount()

extern "C" int getCountForName(const char* name) {
    MyCPPClass mycpp(name);
    return mycpp.getCount();
}

将其编译为共享库,并通过 JNA 加载。

于 2013-04-12T12:12:57.283 回答