0

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);
        }
    }
}
  • Unrelated: I suggest you call your object file `fpp.o` and the actual library `libfpp.so`. Less important but why not rename `main.cpp` into `fpp.cpp` too? – Ted Lyngmo Mar 01 '22 at 11:29
  • You're probably missing a library. The linker will not complain about missing libraries when building another library – user2543253 Mar 01 '22 at 11:54
  • Please provide the full error message but at a guess `-lopencv_core` needs to be at the end of your library list – Alan Birtles Mar 01 '22 at 12:32
  • @AlanBirtles I was on my way of writing an answer because I could reproduce the problem - but suddenly I couldn't reproduce it anymore (it just works fine) - even though I put `-lopencv_core` just where OP put it, so I got delayed trying to figure out what I did to make it work :-) – Ted Lyngmo Mar 01 '22 at 12:35

0 Answers0