Reputation: 1053
I have followed this guide Beginning JNI with NetBeans IDE and C/C++ Plugin on Linux to run 'C' code from my Java application and everything worked.
My issue is when I'm trying to use external libraries (like amqp.h) I'm getting an error:
symbol lookup error: /home/amir/NetBeansProjects/c_pcap_parser/lib/c_pcap_parser.so: undefined symbol: amqp_new_connection Java Result: 127
How ca I include the libraries in my final .so file?
Upvotes: 1
Views: 1967
Reputation: 601
first of all, you should get an basic understanding regarding native libraries on your platform. There are static and dynamic libraries.
Static means that all native code is added into a library file for the purpose of reuse. So if you already compiled some C code you will know about the *.o files, which contain the binary code which is understanded by your processor. A static library is just a collection of them. They usually have the file extention .a on linux platforms. When linking to a static library, all native binrary code will be added to your application (let's say to your executable).
In contrast, a dynamic library will not be added physically into your executable, it will be referenced if required from a global system directory (this is similar to the PATH environment). They are called shared objects on linux (extention .so). There is also an environment variable for that on most platforms, i think it's called LD_LIBRARY_PATH
(see this stack overflow for destinction). All directories of the environment variable will be searched for shared objects which can be linked at startup time to your application.
Ok with that in mind, You can try to solve the problem. I suppose that amqp.h belongs to the C rabbitmq client. If you want to use that c code in java, you need first to compile it on your platform. This is done by following the description on the github project page which I referenced above.
Ok, after a successful build process you will get some library file out of the compilation, I think they will create a dynamic library but I am not sure of that. The result of this outcome determines your action for your java code. If it is a dynamic library, It would be enough to add the shared object to the java native library path. This is also shown in the tutorial that you referenced. I just added a entry for the potential shared object of the rabbitmq c library:
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");
}
If it would be a static library, you would actually need to go different about that. You would need to link the librabbitmq.a library during your C compilation to get things wired up correctly. In the tutorial referenced in your question I saw that Netbeans have a linker section for the C compiler in which you may be capable to add the static lib of rabbitmq during C compilation.
One disclaimer: if you just want to access rabbitmq with java code there of course also exits a java library which should be much easier to use with rabbitmq (you would not need the whole JNI and C compilation things).
Also one note to the given tutorial in your question: They compile the C code with the -m32 flag which produces a 32 bit shared object. If you follow my instructions above this could be a issue! The reason would be that you need to compile the rabbitmq C client also with this flag, to 32 bit. The default gcc compiler on most platforms will produce 64 bit libraries, which are not compatible with a 32 bit JVM and your 32 bit shared library. So ensure all is 32 bit or 64 bit, but not mixed in anyway! For example living on a 64 bit machine, with a 64 bit JVM, you must delete the -m32 flag.
Upvotes: 2