Java JNI' C'代码与外部库

时间:2014-12-29 10:22:40

标签: java c java-native-interface

我已按照本指南Beginning JNI with NetBeans IDE and C/C++ Plugin on Linux运行' C'来自我的Java应用程序的代码,一切正常。

我的问题是当我尝试使用外部库(例如amqp.h)时,我收到错误:

  

符号查找错误:   /home/amir/NetBeansProjects/c_pcap_parser/lib/c_pcap_parser.so:   undefined symbol:amqp_new_connection Java结果:127

我如何在最终的.so文件中包含库?

1 个答案:

答案 0 :(得分:2)

首先,您应该对平台上的本机库有基本的了解。 有静态和动态库。

静态意味着将所有本机代码添加到库文件中以便重用。因此,如果您已经编译了一些C代码,您将了解* .o文件,其中包含处理器所涵盖的二进制代码。静态库只是它们的集合。它们通常在linux平台上具有文件扩展名.a。链接到静态库时,所有本机二进制代码都将添加到您的应用程序中(假设您的可执行文件)。

相反,动态库不会物理添加到您的可执行文件中,如果需要,它将从全局系统目录中引用(这类似于PATH环境)。它们在linux上被称为共享对象(扩展名.so)。在大多数平台上还有一个环境变量,我认为它被称为LD_LIBRARY_PATH(请参阅this堆栈溢出以进行命名)。将搜索环境变量的所有目录以查找可在启动时链接到应用程序的共享对象。

好的,记住,你可以尝试解决问题。我想amqp.h属于C rabbitmq client。如果要在java中使用该c代码,首先需要在平台上编译它。这是通过遵循我在上面引用的github项目页面上的描述来完成的。

好的,在成功构建过程之后,您将从编译中获得一些库文件,我认为它们将创建一个动态库,但我不确定。此结果的结果决定了您对Java代码的操作。如果它是动态库,那么将共享对象添加到java本机库路径就足够了。这也显示在您引用的教程中。我刚刚为rabbitmq c库的潜在共享对象添加了一个条目:

static {
    System.load("full-path-to-NetBeansProjects-dir/JNIDemoCdl/dist/libJNIDemoCdl.so");
    System.load("full-path-to-dir-where-the-rabbitmq-so-lives-in/librabbitmq.so");   
}

如果它是一个静态库,你实际上需要对此有所不同。您需要在C编译期间链接librabbitmq.a库以正确连接。在您的问题中引用的教程中,我看到Netbeans有一个C编译器的链接器部分,您可以在C编译期间添加rabbitmq的静态库。

一个免责声明:如果您只想使用java代码访问rabbitmq,那么当然也会退出java library,这应该更容易与rabbitmq一起使用(您不需要整个JNI和C编译事物)。

还有一个关于你问题中给定教程的注释: 他们使用 -m32 标志编译C代码,该标志产生32位共享对象。如果您按照上面的说明操作,这可能是一个问题!原因是您需要使用此标志将rabbitmq C客户端编译为32位。大多数平台上的默认gcc编译器将生成64位库,这些库与32位JVM和32位共享库不兼容。所以确保所有都是32位或64位,但无论如何都不要混合!例如,生活在具有64位JVM的64位计算机上,您必须删除-m32标志。