使用JNA从Java调用c++ dll方法并避免方法名称混淆
Calling a C++ dll method from Java using JNA and avoiding Method Name Mangling
我一直在通过StackOverflow关于如何解决方法名称混淆的链接,但没有找到任何解决方案与实时示例。
Scenario-A c++ Ex.dll文件由客户端提供。我需要访问exe .dll并通过Java调用相同的方法。
限制-不能修改exe .dll,我只能访问相同的。
面临的问题-当我通过JNA访问exe .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:* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
下面提到的是我通过依赖项漫游器浏览DBMM.dll时得到的实际函数-
DBMM DLL函数-
? ?0 cdbmminterfacecache@@qae@abv0@@z
? ?0 cdbmminterfacecache@@qae@xz
? ?0 cdbmminterfacecontrol@@qae@abv0@@z
? ?0 cdbmminterfacecontrol@@qae@xz
? ?0 cdbmminterfaceecon@@qae@abv0@@z
? ?0 cdbmminterfaceecon@@qae@xz
? ?0 cdbmminterfaceknob@@qae@xz
? ?0 cdbmminterfaceoutput@@qae@abv0@@z
? ?0 cdbmminterfaceoutput@@qae@h@z
? ?0 cdbmminterfacepoolloan@@qae@abv0@@z
? ? 0 cdbmminterfacepoolloan@@qae@v ? basic_string@DU美元? char_traits@D@std@@V美元?美元allocator@D@2@@std@@@Z
? ?0 cdbmmmacroecon@@qae@abv0@@z
? ?0 cdbmmmacroecon@@qae@abvcdbmminterfaceecon@@_n@z
? ?0 cdbmmmtgbasisconstspreadmodel@@iae@xz
? ?0 cdbmmmtgbasisconstspreadmodel@@qae@abv0@@z
? ?0 cdbmmmtgbasisconstspreadmodel@@qae@pbd@z
? ?0 cdbmmmtgbasismodel@@qae@abv0@@z
? ?0 cdbmmmtgbasismodel@@qae@xz
? ?0 cscalefieldssubsum@@qae@nn@z
? ?1 cdbmminterfacecache@@qae@xz
? ?1 cdbmminterfacecontrol@@qae@xz
? ?1 cdbmminterfaceecon@@qae@xz
? ?1 cdbmminterfaceknob@@qae@xz
? ?1 cdbmminterfaceoutput@@qae@xz
? ?1 cdbmminterfacepoolloan@@qae@xz
? ?1 cdbmmmacroecon@@qae@xz
? ?1 cdbmmmtgbasisconstspreadmodel@@uae@xz
? ?1 cdbmmmtgbasismodel@@uae@xz
? ?1 cscalefieldssubsum@@qae@xz
? ?4 cdbmminterface@@qaeaav0@abv0@@z
? ?4 cdbmminterfacecache@@qaeaav0@abv0@@z
? ?4 cdbmminterfacecontrol@@qaeaav0@abv0@@z
? ?4 cdbmminterfaceecon@@qaeaav0@abv0@@z
? ?4 cdbmminterfaceknob@@qaeaav0@abv0@@z
? ?4 cdbmminterfaceoutput@@qaeaav0@abv0@@z
? ?4 cdbmminterfacepoolloan@@qaeaav0@abv0@@z
? ?4 cdbmmmacroecon@@qaeaav0@abv0@@z
? ?4 cdbmmmtgbasisconstspreadmodel@@qaeaav0@abv0@@z
? ?4 cdbmmmtgbasismodel@@qaeaav0@abv0@@z
? ?4 cscalefieldssubsum@@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++的影响。
看起来库是一个JNI库,给定Java_sysInfo_
前缀。如果是这种情况,您只需要声明等效的java端,例如
// default package
public class sysInfo {
static { System.loadLibrary("Ex"); }
public static native int getCPUSpeed();
}
我想你可能会发现这个映射是正确的,你不需要JNA。
编辑
给定一个c++类,具有任意的输入参数和方法getCount()
:
extern "C" int getCountForName(const char* name) {
MyCPPClass mycpp(name);
return mycpp.getCount();
}
编译成一个共享库,并通过JNA加载
如果你通过Visual studio构建DLL,如果你还没有这样做,你应该能够将它作为一个发布版本来构建,而不是调试来修复函数名。
- 重写另一个方法 [C++] 使用的超类回调函数
- C++ push() 和 pop() 方法使用指针的动态 LinkedList 的问题
- const 方法使用引用修改对象
- WriteJPGBuffer 方法使用 libjpeg 库而不是 ijl15.lib
- 对成员类型的成员方法使用 std::result_of<>
- 有没有办法强制对 clang-format/clang-tidy 中的类成员/方法使用 "this->"?
- 如何通过方法使用抽象类的子实例?
- 当被调用方法使用调用方已锁定的同一锁时,如何避免死锁
- 如何使用很少的方法使用 1 个数组
- 使用超载方法使用std :: result_of
- 通过通过类方法使用Wire.Onrequest
- C++,在哈希表中显示内容的方法.使用双链表
- 我正在尝试创建一个方法,该方法使用指针算术返回一对,它是否会出错
- 未解析的外部符号静态变量(标头中定义的方法使用的变量)
- 在哪里/如何声明和实现必须由成员方法使用的帮助函数
- 检查所有__m128i组件是否为 0 的最有效方法 [使用 <= SSE4.1 内部函数]
- 模板类的方法使用全局范围内的 typedef.编译器错误
- C++返回对成员的连接文件,因此可以由同一类的其他方法使用
- 在模板中调用派生类对象的方法 [使用 dynamic_cast]
- 如何指定C++类的特定方法使用模板