0

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/TestErrorOnLibrary

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::Mat one);
};

#endif // PROCESSMATINLIBRARY_H

Files to create my library

processmathinlibrary.cpp

#include "processmatinlibrary.h"

using namespace std;
using namespace cv;

#include <iostream>

ProcessMatInLibrary::ProcessMatInLibrary()
{
    cout << "Initialized " << endl;
}

bool ProcessMatInLibrary::flip(cv::Mat image)
{
    cout << "** Inside Library: " << endl;
    if(image.empty())
    {
    cout << " Image is empty" << endl;
    return false;
    }
    cout << " Image is not empty " << endl;

    //    return false;
    Mat image2;
    cv::flip(image, image2, 0);

    imshow("Image in library", image);
    imshow("Image2 in library", image2);
    waitKey(0);

    cout << "Inside Library: Image is not empty" << endl;
    return true;
}


bool ProcessMatInLibrary::myTest(cv::Mat one)
{
    one.copyTo(_img);
}

processmathlibrary.h

This is my private header, used to compile my library, it only differs on private declarations

#ifndef PROCESSMATINLIBRARY_LIB_H
#define PROCESSMATINLIBRARY_LIB_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::Mat one);
private:
    cv::Mat _img;
};

#endif // PROCESSMATINLIBRARY_LIB_H

How to compile all of this

CMakeLists.txt

Note that I have defined other PATH for OpenCV library, maybe there is an error to compile in the default PATH, I cannot check that find_package(OpenCV REQUIRED) is working

cmake_minimum_required(VERSION 2.8.12)

project(test_pub_priv)

set(CMAKE_CXX_FLAGS "-Wall -Wextra -O3 -std=c++11")

#set(OpenCV_INCLUDE_DIRS "./include/")

find_package(OpenCV REQUIRED)

message(" ** Test with public private libraries ** ")

include_directories(${OpenCV_INCLUDE_DIRS})

aux_source_directory(./src SRC_LIST)
include_directories(./hpp SRC_LIST)
FILE(GLOB_RECURSE LibFiles "./hpp/*.h")
add_custom_target(headers SOURCES ${LibFiles})

add_library(myFramework ${SRC_LIST} )
add_executable(test_pub_priv ./examples/Main.cpp)
target_link_libraries(test_pub_priv ${OpenCV_LIBS} myFramework)

My question and problem is: What is the right way to pass a cv::Mat as argument trough library with one private header to the library and other (public header) to be shared?

Complete code can be seen here:

https://github.com/eld1e6o/TestErrorOnLibrary

Thanks!

Community
  • 1
  • 1
Diego
  • 35
  • 7
  • 2
    Is that even valid in C++? Declare two different classes from two different header files with the same name but pass them around as the same thing? – fdk1342 Dec 20 '18 at 19:41
  • Hello @Fred , thanks for your comment. It is possible but I don't know how to do this. I'm faulting but I don't know where or how to solve this! It seems that addresses are different or something like this. – Diego Dec 20 '18 at 19:47
  • 2
    I have not read your post in details, just skimmed through it. But, I get the impression that you are maybe running into undefined behaviour due to a ODR violation. Maybe C++17 "inline variables" are what you want. As I said, I didn't read carefully, so I may be completely off target. Just wanted to share what I got from a quick skim. – Jesper Juhl Dec 20 '18 at 20:07
  • 2
    @JesperJuhl I think you are correct in that it is an ODR violation. Comparing `"processmatinlibrary.h` and `processmatinlibrary_pub.h` have the same class but with two different definitions. Each translation unit gets a different header file so the object as created in Main.cpp won't even have space for the private variable that the library functions expect. This can be verified with sizeof(). – fdk1342 Dec 20 '18 at 21:31
  • @Fred you are right! Great. Thanks! It has sense, my problem is a common problem. How do I will isolate libraries, including his private headers, of public headers to include in main code? What Is the correct way? Thanks for all! – Diego Dec 21 '18 at 01:48
  • @JesperJuhl you have reason, thanks also! I'm searching for the best way to define the public and private headers. I'm searching how to do inline variables in classes. Do you have some hint? Thanks for your time! – Diego Dec 21 '18 at 04:07
  • https://stackoverflow.com/questions/38043442/how-do-inline-variables-work I don't think this is what you want because every example I saw was for static variables in a class. – fdk1342 Dec 21 '18 at 12:19
  • Possible duplicate of [Private/public header example?](https://stackoverflow.com/questions/2272735/private-public-header-example). Here is what I found... – fdk1342 Dec 21 '18 at 12:21

0 Answers0