当前位置: 首页 > 知识库问答 >
问题:

通过gcc[有效]和g++[失败]对C dll的Java调用

贡念
2023-03-14
void Java_TEST_run(){}
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 -c  TEST.c
g++ -shared  -o TEST.dll TEST.o
g++ -c  TEST.c
g++ -shared  -o TEST.dll TEST.o
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)

我对Java还很陌生,对上面的问题感到迷茫。C代码是我所能想象的最小的代码,不包括任何参数、头或JNI。编译和链接可以与gcc和g++一起工作,但在执行时会找到g++编译的DLL,但会创建UnsatisfiedLinkError。我假设G++编译可能会更改函数名(“java_test_run”)。我尝试了许多不同名字的组合,但都没有成功。

如果有人能在这个问题上给我一些启发或提示,我非常感谢您的帮助!

非常感谢,马丁

共有1个答案

拓拔谭三
2023-03-14

C和C++是不同的语言,遵循不同的编译规则。如果使用g++进行编译,那么代码将被视为C++而不是C。常见的误解是C++是C的超集。

C++做了一件叫做名称混淆的事情:将函数和变量名编码成唯一的名称,这样链接器就可以将语言中的通用名称分开。多亏了它,像函数重载这样的特性才成为可能。

让我们考虑一个例子(出处):

int  f (void) { return 1; }
int  f (int)  { return 0; }
void g (void) { int i = f(), j = f(0); }
int  __f_v () { return 1; }
int  __f_i (int)  { return 0; } 
void __g_v () { int i = __f_v(), j = __f_i(0); }
 类似资料:
  • 我有一个简单的JNI.dll,试图在测试Java应用程序中使用它。它是一个文件,由几个函数组成,头部由生成。(我正在使用MinGW btw编译) 如果我用GCC编译并链接这段代码,我就可以很好地用system.loadLibrary()加载.dll并使用它。但是,如果我用G++编译它,将失败,出现可怕的“UnsatisfiedLinkError”。 g++-wl,--add-stdcall-ali

  • 我如何强制gcc/g不使用寄存器,而只使用x86\u 64中的堆栈将参数传递给函数,就像在32位版本中一样(并可能以这种方式获取函数结果)。我知道它破坏了官方ABI,调用方和被叫方都必须以这种方式编译,这样它才能工作。我不在乎是否使用推送/弹出或移动/子方式。我希望编译器应该有一个可以强制执行它的标志,但我找不到它。

  • 发展至今(2020 年 6 月份),GCC 编译器已经更新至 10.1.0 版本,其功能也由最初仅能编译 C 语言,扩增至可以编译多种编程语言,其中就包括 C++ 。 除此之外,当下的 GCC 编译器还支持编译 Go、Objective-C,Objective-C ++,Fortran,Ada,D 和 BRIG(HSAIL)等程序,甚至于 GCC 6 以及之前的版本还支持编译 Java 程序。但本

  • 我不能用REmover类直接擦除代码对象...它给了我一个错误...但是当我第一次用我的代码删除连接的注释时,然后删除已经完成的代码...是否有其他方法可以自动删除代码和代码对象的注释?关于... 警告:SQL错误:0,SQLSTATE:23503 2013年6月24日2:25:51 PM org.hibernate.engine.jdbc.spi.sqlExceptionHelper logEx

  • 问题内容: 我有一个将数据发送到Web服务器的桌面客户端,但是我似乎无法通过代理服务器。 更新 :尝试通过代理进行通信时,我收到407 HTTP错误。 从我的Web服务器下载信息时,一切都很好。用户配置代理服务器后(使用我编写的对话框),下载工作正常。但是使用org.apache.http.client.HttpClient上传数据不起作用。 从JDialog收集信息后,我将使用以下代码配置代理服

  • 当我编译我的项目并检查运行所使用的资源时,大CPU/内存猪有时被称为,有时被称为。两者之间有什么区别,我是否应该直接调用?