Ask Your Question
0

Correct way to make library with priv / public header and pass cv::Mat

asked 2018-12-20 13:08:44 -0600

eld1e6o gravatar image

updated 2018-12-20 13:09:54 -0600

Hello!

I need to make a .so or .a library and different headers, one of them to be shared with users to compile my main program (and link, in the code, processmatinlibrary_pub.h) and other to use in definitions and separated to the main code (processmatinlibrary.h).

When I use the public header (whitout some private definitions of methods), some times, depending on the structure of my program, I get segmentation faults or opencv assertions, below I paste my code, it could be dowloaded from https://github.com/eld1e6o/TestErrorO...

Here is my code and some comments

Files to create my main program, that uses functions on my library

This is the main function, I use it to check the library with public header I get some segmentation faults depending on the structure of my program I can force errors commenting #defines

#define _MAKE_ASSERT_OPENCV 1
#define _MAKE_SEGFAULT_ 1

*If I change the public header to the private header, I have not problems:

#include "processmatinlibrary.h" it works but the headers are not cshared

Instead of

#include "processmatinlibrary_pub.h"

It seems that is a stack problem and I need to define the library or the headers in the right way

Main.cpp

#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include "processmatinlibrary_pub.h"  //If I change this header to #include "processmatinlibrary.h" it works but the headers are not cshared 

using namespace std;
using namespace cv;

#define _MAKE_ASSERT_OPENCV 1
//#define _MAKE_SEGFAULT_ 1

void testEmpty(cv::Mat test_img, std::string msg)
{
    cout << "* Check empty " << msg ;
    if(test_img.empty())
    {
    cout << ": Image is Empty " << endl;
    exit(1);
    }
    else cout << ": Image is not empty " << endl;
}

int main(int argc, char* argv[])
{
    // Classify and get probabilities
    Mat test_img = imread(argv[1], CV_LOAD_IMAGE_COLOR);

    testEmpty(test_img, "After load image");

    cv::resize(test_img, test_img, cv::Size(256, 256));

    cout << " After resize " << endl;

    testEmpty(test_img, "Before initialize library ");

    ProcessMatInLibrary matToLibrary;

#ifdef _MAKE_SEGFAULT_
    return 0; // If I comment this line, I got a segmentation fault: Segmentation Fault (`core' generated)

#endif
    testEmpty(test_img, "After initialize library ");

    bool b = matToLibrary.flip(test_img);

    testEmpty(test_img, "After use function in library ");

    cout << "In main " << endl;
    /*
     * If I define _MAKE_ASSERT_OPENCV, I got errors
    OpenCV(3.4.1) Error: Assertion failed (0 <= _dims && _dims <= 32) in setSize, file /home/diego/Code/opencv/modules/core/src/matrix.cpp, line 209
    terminate called after throwing an instance of 'cv::Exception'
      what():  OpenCV(3.4.1) /home/diego/Code/opencv/modules/core/src/matrix.cpp:209: error: (-215) 0 <= _dims && _dims <= 32 in function setSize
    */
#ifndef _MAKE_ASSERT_OPENCV
    imshow("Test before close", test_img); //If i comment this two lines, I got segmentation faults (OpenCV exception)
    waitKey(0);
#endif
}

processmathlibrary_pub.h

This is my public header, used to define functions as publics

#ifndef PROCESSMATINLIBRARY_H
#define PROCESSMATINLIBRARY_H

#include <opencv2/imgproc.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>

class ProcessMatInLibrary
{
public:
    ProcessMatInLibrary();
    bool flip(cv::Mat image);
    bool myTest(cv ...
(more)
edit retag flag offensive close merge delete

Comments

please do NOT delete previous posts to the same topic, and then post a new one here.

berak gravatar imageberak ( 2018-12-20 14:55:17 -0600 )edit
2

i can't reproduce the error when compiled with VS2017 on windows OpenCV 4 see cloned repo and get output as screenshot

sturkmen gravatar imagesturkmen ( 2018-12-20 20:08:26 -0600 )edit

@berak, thanks for your reply, my old post was an entire disaster and to maintain some level, I redo it. It is not necesary to mark all of my posts with -1, and you can communicate this kind of things trough PM (it is not related directly to the problem).

eld1e6o gravatar imageeld1e6o ( 2018-12-20 21:08:27 -0600 )edit

@sturkmen, very thanks for your time and to test my code. I'm advancing and seing that I'm making some type of ODR (https://en.wikipedia.org/wiki/One_Def...), it seems that size of the object allocated in main class is different to the size of the object in the library, the errors are due to memory protection, sometimes memory allocation corresponds to this code and sometimes not, it depends of the compilation, but it is bad in all cases. I'm checking some good approach to solve this (If you know it, it will be welcomed). I will update. Thanks!

eld1e6o gravatar imageeld1e6o ( 2018-12-20 21:15:06 -0600 )edit

I have created a branch (badsolution), that is working but it is only conceptual. I reserve static memory inside public definition class (of size cv::Mat), in order to coincide with final size. It works but that is not the right way.

eld1e6o gravatar imageeld1e6o ( 2018-12-20 21:27:16 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-12-21 00:09:29 -0600

berak gravatar image

updated 2018-12-21 00:13:58 -0600

having 2 classes with the same name, but a different memory layout in your program is a design desaster. (and the reason for your mysterious segfaults). use interfaces, virtual functions and inheritance instead:

// public (API) header:

struct MyProcessing {
       virtual ~MyProcessing() {}

       virtual bool func1(const Mat &input, Mat &output) = 0;
       virtual bool func2(Mat &input) = 0; // modify in-place
private:
       MyProcessing() {} // not allowed to use
};

// "factory" function
Ptr<MyProcessing> createMyProcessing();

// private implementation:

struct MyProcessingImpl : public MyProcessing {
       bool func1(const Mat &input, Mat &output)  {
             ...
       }
       bool func2(Mat &input) {
             ...
       }

       Mat privateData;
       int foo;
};

// "factory" function, returns implementation class
Ptr<MyProcessing> createMyProcessing() { return makePtr<MyProcessingImpl>(); }

// usage

 Ptr<MyProcessing> process = createMyProcessing();
 Mat input = ...
 Mat output;
 process->func1(input, output);
 // no cleanup nessecary
edit flag offensive delete link more

Comments

I have created a branch (badsolution), that is working but it is only conceptual. I reserve static memory inside public definition class (of size cv::Mat), in order to coincide with final size. It works but that is not the right way. iTunesMobdroTutuApp

Morichtykoko gravatar imageMorichtykoko ( 2019-01-01 04:43:46 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-12-20 13:08:44 -0600

Seen: 369 times

Last updated: Dec 21 '18