通过gcc[works]和g++[失败]对C dll的Java调用
我尝试调用这个名为TEST.C的最小虚拟C程序:通过gcc[works]和g++[失败]对C dll的Java调用,java,c++,c,gcc,g++,Java,C++,C,Gcc,G++,我尝试调用这个名为TEST.C的最小虚拟C程序: void Java_TEST_run(){} 从这个名为Example.Java的Java代码中: public class Example { public static void main(String args[]) { System.out.println("START"); TEST test = new TEST(); test.dll_call
void Java_TEST_run(){}
从这个名为Example.Java的Java代码中:
public class Example
{
public static void main(String args[])
{
System.out.println("START");
TEST test = new TEST();
test.dll_call();
System.out.println("ALL DONE!");
}
}
class TEST
{
public void dll_call()
{
run();
}
static {
try {
System.out.println("Load DLL = start ");
System.load("/home/user/Desktop/TEST.dll");
System.out.println("Load DLL = finish ");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load.\n");
System.exit(1);
}
}
public native void run();
}
如果我使用gcc进行编译,那么一切都很好:
gcc -c TEST.c
g++ -shared -o TEST.dll TEST.o
但如果我使用g++进行编译,如下所示:
g++ -c TEST.c
g++ -shared -o TEST.dll TEST.o
在运行Java示例时,我收到以下错误输出:
START
Load DLL = start
Load DLL = finish
Exception in thread "main" java.lang.UnsatisfiedLinkError: 'void TEST.run()'
at TEST.run(Native Method)
at TEST.dll_call(Example.java:21)
at Example.main(Example.java:9)
我的操作系统是Ubuntu 18.04和openjdk 11.0.6
我对Java非常陌生,对上面的问题非常迷茫。C代码是我所能想象的最小的,不包括任何参数、头或JNI。编译和链接同时适用于gcc和g++,但在执行时会找到g++编译的DLL,但会创建不满意的链接错误。我假设g++编译可能会更改函数名Java\u TEST\u run。我尝试了许多不同名字的组合,但没有成功
如果有人能在这个问题上给我启发或暗示,我非常感谢你的帮助
非常感谢,,
马丁 < P> C和C++是不同的语言,遵循不同的编译规则。如果用G++编译,那么代码将被视为C++而不是C++。 C++做了一件称为名称混乱的事情:将函数名和变量名编码为唯一的名称,以便链接器可以分离语言中的常用名称。多亏了它,像函数重载这样的特性才成为可能
让我们考虑一个例子:
int f void{return 1;} int f int{返回0;} void g void{int i=f,j=f0;} 编译器可将上述内容更改为: int_uuf_uv{return 1;} int{return 0;} void{int i={uu f_v,j={uu f_i0;} 尽管g的名称是唯一的,但它仍然被损坏。名称的缩进适用于所有C++符号。如果你想防止名字的篡改,你需要使用块,但是上面的例子会导致错误,因为C没有函数重载。
< P>如在另一个答案中解释的,这个失败的原因是C++编译器的名字篡改。为了解决这个问题,即使C++与java JNI一起工作,需要用C++的外部声明来修饰C++函数:
外部C 无效Java_测试_运行{}这回答了你的问题吗?非常感谢,这对我很有用!谢谢你,我同意这似乎与“弄脏”这个名字有关。我尝试了一些组合,包括跑步,但对我来说没有效果。。。不管怎样,externC命令成功了。