JNI and shared library - java-native-interface

Trying to create dll.
So first I created a .java file as follows:
class Main
{
static
{
System.loadLibrary("sample_dll");
}
static native void sritest();
public static void main(String [] a)
{
sritest();
}
}
Then I compile it with no error to .class.
Then using javah I created Main.h.
Then I write following code in c++.
#include <jni.h>
#include <Main.h>
JNIEXPORT void JNICALL Java_Main_sritest(JNIEnv *env,jobject obj)
{
printf("hi");
}
Then I compiled this using MinGw by the following code
g++ -c sample_dll.cpp
g++ -shared -o sample_dll.dll sample_dll.o
Then I place this in java library path.
Then I run Main.java but the following exception occurs
Unstatisfied link error; sritest ()V

I find an answer . It is i do three mistakes. When compiling with c++ we must declare my jni function in extern "C"{} block. Second when compiling in minGW compiler we should use following code and implement include folder of jdk . The code now worked and my program runs smoothly without problem in jni.
The command line code for compiling .o to .dll code is after creating sample_dll.o we must do
g++ -Wall -D_JNI_IMPLEMENTATION -Wl,--kill-at -Ic:/path_of_include_folder_in_jdk_without_drive_letter -Ic:/path_of_win32_folder_in_include_folder_in_jdk_without_drive_letter -shared -o sample_dll.dll sample_dll.o
The last mistake is i want to include Main.h compiled by javah utlity that created from my java code.
This is done by
Javac Main.java
Javah Main
Then take the header file Main.h created and place it in the c++ compiler's include folder. That in my computer c:\minGW\include .
In c++ code add additional preprocessor
#include<Main.h>
All done create dll and place it in one of default java library path . The paths can be getted by using the following function in java
System.out.println (System.getProperty ("java.library.path"));

Related

C++ library in Visual Studio Code

I have made a c++ project in CodeBlocks. Now I started using Visual Studio Code and I can't figure out how to connect files. I have main.cpp with my main code, then I have sortlib.cpp with some sorting functions and I have sortlib.h. My question is how do I connect these files, so I can #include "sortlib.h" in my main.cpp file and use the functions.
I have tried including sortlib.h in my sortlib.cpp program and then my sortlib.h in my main.cpp program, but it didn't work.
I'm on windows so I just compiled my sortlib.cpp program by typing g++ sortlib.cpp and it showed me this error message
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../libmingw32.a(main.o):(.text.startup+0xc0): undefined reference to 'WinMain#16'
Minimal code structure
main.cpp
// Other header files
#include "sortlib.h"
int main(void) {
...
}
sortlib.h
void someFunction();
...
sortlib.cpp
// Include headers that are required
void someFunction() {
...
}
The minimal required command
g++ -g main.cpp sortlib.cpp
There is no such thing as "connecting" files in programming. You have to make sure that your compiler is compiling all the .cpp files into .o/.obj files and that they are all getting linked together to produce your final executable.

"undefined reference to `WinMain#16'" Error in gcc editor

I am just learning c++ and began to watch a youtube tutorial by thenewboston. Unfortunately he is using Code::Blocks while I am using gcc and I do not have the option to create new class files with a button click and so had to manually create them.
I dont understand why the same code in Code::Blocks and gcc will work in Code::Blocks but not gcc. Does gcc require different coding for the same language?
EDIT: I have downloaded and tested in Code::Blocks myself
Other questions talk of how I need to give windows an entry point, but I dont know how to do that.
Test.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
int main() {
ClassTest bo;
}
ClassTest.h Code:
#ifndef CLASSTEST_H
#define CLASSTEST_H
class ClassTest {
public:
ClassTest();
};
#endif // CLASSTEST_H
ClassTest.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
ClassTest::ClassTest() {
cout << "blah blah" << endl;
}
I'm not quite sure I understand what the question is; I'm going to take it as "how do I get these three files to build into a .exe that I can run from the Windows commmand line?"
The answer is to run something like this on the command line, in the folder with the files:
g++ -c Test.cpp -o Test.o
g++ -c ClassTest.cpp -o ClassTest.o
g++ Test.o ClassTest.o -o Test.exe
The first two commands build each CPP file into an "object file", which isn't a whole program by itself but which contains the compiled version of the code in that CPP file. The last command tells the compiler to paste together the two object files into a program, and resolve all the cross-references between them. (For example, the part where Test.cpp constructs a ClassTest object needs to end up calling the ClassTest constructor code from ClassTest.cpp.)
Code::Blocks is an IDE and works out how to build each source file in your project and link them together by itself. But if you aren't using an IDE, you need to do that in another way. You can either do it manually like this, or you can write a Makefile that will check which code files have changed and rebuild and re-link everything that depends on them when you run the make command, which is how most people do it.
As for "giving Windows an entry point", that probably refers to GUI applications that want to display windows on the screen. For console programs like the one you have written, the "entry point" is main(), and you just print stuff to the command line window. To make actual Windows-style GUI windows of your own, you need to use the Windows API, which I can't tell you much about.

Eclipse CDT Including Unreferenced Files in Automatically Generated Build

I'm new to cpp in eclipse and trying to mess with simple builds. I have made a basic project which automatically generates build info (no user-defined makefile).
Simple (Working) Case
I made a "Hello World" project called Test (not an empty project). It has one file - Test.cpp with a main() in => builds and runs fine.
Test.cpp
int main() {
// output some stuff
}
Slightly More Complex (Working) Case
I make a new file called Main.cpp. Move the main() function into Main.cpp and make a decleration of a function in main too - void test();
The test() function lives in Test.cpp, which is where I provide the function definition.
Main.cpp
#include <iostream>
void test();
int main() {
// Use test()
}
Test.cpp
#include <iostream>
void test() {
// output some stuff
}
Build it, there are now two .o files in the Debug directory - Test.o and Main.o. This runs fine.
The Problem
Now I try to introduce a third file - Limits.cpp.
Limits.cpp
#include <iostream>
void printLimits() {
// Print out limits for different integer sizes
}
Again I provide a deceleration of this function in Main.cpp.
Main.cpp
#include <iostream>
void test();
void printLimits();
int main() {
// Use printLimits()
}
This time there is no object file created for Limits in the Debug folder => the build fails.
Main.cpp:*line* undefined reference to `getLimits()'
It just looks like the autogenerated build config for the project is duff. I've tried looking around the project properties but I have had no luck. I've tried including the path/file in Include Paths/Include files, other objects, and I've checked just about every other property I can see. This has been frustrating me for two days.
The strange thing about this is case 2. It looks like because Test.cpp was the first file made it always includes this in the build? (even if it is not imported). Where as because Limits.cpp is new and not imported it doesn't generate an object file so it can't link the function.
I could me making an error by needing to include the files but my understanding is if all the object files make it to the linker then all will be well (ie I just need the function declarations when making the object files which is what I have here).
With a "Blank project" it seems to compile all the cpp files even if they are never used so my case above works. (Although, it doesn't work for files in subfolders of src). Looks like its a "feature" of the "Hello world" project type but it's going to drive me crazy knowing there must be a way to get it to do this.
If anyone knows if it is possible to include this file without writing my own makefile (I'm not a makefile guru (yet!)), or let me know if this is not possible with autogen CDT that would be great.
Using MinGW GCC toolchain.
Thanks

Calling a shared library from c++

i have a shared library with some functions stored inside it. i want to Access those functions by calling that library from another program. I have done this earlier in C.
Now i want to do the same using C++. I am pretty new to C++ and any suggestions are very much required. BTW, the shared library is written in C. Is it still possible for me to call this in a C++ program and use all the functions of it.
Please help me. An example program would be very very helpful.
i am using ubuntu 14.04 and the compiler is the native g++ that comes along with it.
Load shared libarary using dlopen, and load given symbol using dlsym. Link with -ldl.
So given a shared library hello.cpp, compile g++ -shared -fPIC -o libhello.so hello.cpp
#include <cstdio>
extern "C" void hello( const char* text ) {
printf("Hello, %s\n", text);
}
(shared libraries should be named lib*.so[.*])
Now calling in main.cpp, compile: g++ -o main main.cpp -ldl
#include <dlfcn.h>
extern "C" typedef void (*hello_t)( const char* text );
int main() {
void* lib = dlopen("./libhello.so", RTLD_LAZY);
hello_t hello = (hello_t)dlsym( lib, "hello" );
hello("World!");
dlclose(lib);
}
See C++ dlopen mini HOWTO.
You said you already did so in C. Actually C++ is based on C, so you still can do it in the same way you did before.
Usually the following steps are required:
Use some method provided by the library in your c++ code
Figure out which header provides that method, and include it in your .cpp file
Compile your C++ code against the headers of the library (compiler flags in the Makefile)
Link against the library ( Linker Flags in the Makefile )

Python importing & using cdll (with a linux .so file)

After one of my last questions about python&c++ integration i was told to use dlls at windows.
(Previous question)
That worked ok doing:
cl /LD A.cpp B.cpp C.pp
in windows enviroment, after setting the include path for boost, cryptopp sources and cryptopp libraries.
Now i'm tryting to do the same in linux, creating a .so file to import through ctypes on python2.5.
I did:
gcc -Wall -Wextra -pedantic A.cpp B.cpp C.cpp /usr/lib/libcryptopp.so -shared -o /test/decoding.so
and the so object is created ok. If removed "-shared" compilation is OK but stops as no main in there (obviously ;) ). Of course libcryptopp.so exists too.
But when i go to python and import the "so" file, it said that the attribute has no object "decrypt", "encrypt" or whatever i put there. using "dir" over the dll objects confirms that they are not there.
external functions are defined in A.cpp as:
int encrypt (params...)
//..
return num;
int decrypt (params...)
//..
return num;
also tried using:
extern "C" encrypt (params...)
.....
Could anyone tell me what i'm doing wrong?
Thanks in advance!
Rag
C++ compiler mangles names of functions. To do what you are trying to do you must have the declaration prototype inside
extern "C" {...}
it's hard to tell from your samples what exactly you have in a source file.
As someone already mentioned, use nm utility to see what objects that are in your shared object.
Do not compile your object without -shared. Python load library does not support statically linked objects as far as am aware.
compile your object with g++ compiler instead, it will link to standard C++ Library, gcc does not.
just to doublecheck something since you using boost.
#include <string>
#include <boost/python.hpp>
using namespace std;
string hello(string s){
return "Hello World!";
}
BOOST_PYTHON_MODULE(pyhello){
using namespace boost::python;
def("hello", hello);
}
in python
>>> import pyhello
>>> print pyhello.hello()
Hello World!
just my 2 cents, sorry if this couldn't help you.