I'm trying to compile a c++ file into a shared library (extension .so) and it's ok, I can generate the shared library perfectly, the problem comes when I try to use the shared library through Java with JNI, it gives me "undefined symbol : _ZN2cv3MatC1Ev" error.
OBSERVATIONS: I'm using g++ to compile. To run the Java class I'm using the oracle-jdk-8.
Compile from c++ to .so file with g++:
g++ -c -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux ../main.cpp -I./ -I/usr/local/include/opencv4/opencv2 -L/usr/local/lib/ -I/usr/local/include/opencv4 -lopencv_objdetect -lopencv_features2d -lopencv_imgproc -lopencv_highgui -lopencv_core -lopencv_videoio -lopencv_calib3d -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_imgcodecs -I./../ -I/usr/local/include/opencv4/opencv2/core -fPIC -o libfpp.o
g++ -shared -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -I./ -I/usr/local/include/opencv4/opencv2 -L/usr/local/lib/ -I/usr/local/include/opencv4 -lopencv_objdetect -lopencv_features2d -lopencv_imgproc -lopencv_highgui -lopencv_core -lopencv_videoio -lopencv_calib3d -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_imgcodecs -I./../ -I/usr/local/include/opencv4/opencv2/core -fPIC -o fpp.so libfpp.o -lc
My c++ file and header:
main.cpp
#include <iostream>
#include <jni.h>
#include <Main.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <string>
#include <vector>
#define PIC_PATH "/home/isomeister/cap2.jpg"
using namespace std;
using namespace cv;
//VideoCapture cap(0);
vector<Point> biggerContour;
vector<double> barCodeXPos;
int t1 = 204, t2 = 255, t3 = 0;
/**
* @brief save the gived frame in a file.
*
* @param video The frame in format of cv::Mat.
* @param resolution The resolution that the picture must be saved.
*/
void takePicture(Mat video, Size resolution) {
Mat dst;
resize(video, dst, resolution);
//imwrite(PIC_PATH, dst);
}
void getCountours(Mat img, Mat source) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(img, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//drawContours(source, contours, -1, Scalar(255, 0, 255), 2);
int biggerArea = 0;
for (int i = 0; i < contours.size(); i++) {
//cout << "\nX " << boundingRect(contours[i]).x << "Y " << boundingRect(contours[i]).y << "W ", boundingRect(contours[i]).width, "H ", boundingRect(contours[i]).height;
//cout << "| Area: " << boundingRect(contours[i]).area() << "\n";
if (boundingRect(contours[i]).y > 40 || boundingRect(contours[i]).x > 155) {
if (boundingRect(contours[i]).y < 10) {
continue;
}
continue;
}
int area = contourArea(contours[i]);
barCodeXPos.push_back(boundingRect(contours[i]).x);
if (area > biggerArea) {
biggerArea = area;
biggerContour = contours[i];
cout << "\nX " << boundingRect(biggerContour).x << " Y " << boundingRect(biggerContour).y << " W ", boundingRect(biggerContour).width, " H ", boundingRect(biggerContour).height;
cout << "| Area: " << boundingRect(biggerContour).area() << "\n";
continue;
}
/*
circle(res, Point(20, 17), 10, Scalar(173, 24, 11), FILLED);
circle(res, Point(81, 31), 10, Scalar(250, 228, 85), FILLED);
circle(res, Point(145, 30), 10, Scalar(35, 233, 250), FILLED);
*/
}
}
int getPos() {
sort(barCodeXPos.begin(), barCodeXPos.end());
for (int j = 0; j < barCodeXPos.size(); j++) {
cout << " Barcodex Pos: " << barCodeXPos[j] << "\n";
if (boundingRect(biggerContour).x == barCodeXPos[j]) {
cout << "Game element in the: ";
if (j == 0) {
cout << "left \n";
return 0;
} else if (j == 1) {
cout << "right \n";
return 1;
} else if (j == 2) {
cout << "center \n";
return 2;
} else {
return -1;
}
}
}
return -2;
}
/**
* @brief
*
* @param path
* @param redSide
*/
void recognize(Mat path, bool redSide) {
Mat res, gray, tresh;
resize(path, res, Size(200, 200));
cvtColor(res, gray, COLOR_BGR2GRAY);
threshold(gray, gray, t1, t2, t3);
getCountours(gray, res);
cout << "AREA BIG CONTOUR: " << boundingRect(biggerContour).area() << "\n";
circle(res, Point(boundingRect(biggerContour).x, boundingRect(biggerContour).y), 10, Scalar(255, 0, 255), FILLED);
//drawContours(res, biggerContour, -1, Scalar(255, 0, 255), 2);
//imshow("resized", res);
//imshow("marked", gray);
//waitKey(0);
}
/*int main(int, char **) {
cout << "Code initialized (C++)!";
return 0;
}*/
JNIEXPORT jint JNICALL Java_Main_fpp
(JNIEnv *, jobject) {
Mat source;
//cap.read(source);
//cout << "Capturing image...";
//takePicture(source, Size(150, 200));
cout << "Recognizing image...";
recognize(imread(PIC_PATH), false);
return getPos();
}
void say_hello(){
std::cout << "Hello, from ffp!\n";
}
Main.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */
#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Main
* Method: fpp
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_Main_fpp
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Java class
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
static {
System.loadLibrary("fpp");
}
private native int fpp();
public static void main(String[] args) {
System.out.println(System.getProperty("java.library.path"));
try {
System.out.println("java test");
int junk = new Main().fpp();
System.out.println("C exit: " + junk);
} catch (Exception ex) {
System.out.println(ex);
}
}
}