Error in making DLL class in Eclipse IDE with g++ compiler - c++

I make a project in Eclipse to export a dll class with g++ compiler. My OS is Ubuntu and the application will run in Ubuntu OS. I created a shared project.
I have compile error as
expected constructor, destructor, or type conversion before ‘(’ token OCR_dll.h /OCR line 19 C/C++ Problem
The error happened at #define DLLCLASS __declspec(dllexport) and how to solve the error. Thank you.
My dll codes header file is
OCR_dll.h
#ifndef OCR_DLL_H_
#define OCR_DLL_H_
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <tesseract/baseapi.h>
#include <iostream>
#include "Define.h"
#ifdef EXPORT
#define DLLCLASS __declspec(dllexport)
#else
#define DLLCLASS __declspec(dllimport)
#endif
using namespace cv;
#ifdef __cplusplus
extern "C" {
#endif
namespace VIDEOANALYTICS_PLATFORM {
class iOCR{
public:
virtual ~iOCR(){}
virtual int preProcessing(Mat &img) = 0;
virtual int textExtraction(Mat &img) = 0;
};
class OCR : public iOCR{
public:
OCR(){}
~OCR(){ ; }
int preProcessing(Mat &img);
int textExtraction(Mat &img);
private:
};
extern "C"{ DLLCLASS iOCR* __stdcall createOCRObject(); };
}
#ifdef __cplusplus
}
#endif
#endif /* OCR_DLL_H_ */

I got the solution. In Linux environment, dll is called shared library.
The way I create the shared lib is
Headerfile
#ifndef OCR_DLL_H_
#define OCR_DLL_H_
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <tesseract/baseapi.h>
#include <iostream>
#include "Define.h"
using namespace cv;
namespace VIDEOANALYTICS_PLATFORM {
class iOCR{
public:
virtual ~iOCR(){}
virtual int preProcessing(Mat &img) = 0;
virtual int textExtraction(Mat &img) = 0;
};
class OCR : public iOCR{
public:
OCR(){}
~OCR(){ ; }
int preProcessing(Mat &img);
int textExtraction(Mat &img);
private:
};
}
#endif /* OCR_DLL_H_ */
CPP file
#include "OCR_dll.h"
namespace VIDEOANALYTICS_PLATFORM {
extern "C" iOCR* create_object(){
iOCR *p = new OCR();
return p;
}
extern "C" void destroy_object( iOCR* object )
{
delete object;
}
int OCR::preProcessing(Mat &img){
return SUCCESS;
}
int OCR::textExtraction(Mat &img){
return SUCCESS;
}
}
MAKEFILE
g++ -fPIC -shared OCR_dll.cpp -o OCR_dll.so
Then we can create shared lib object for a class.

Related

Can I generate DLL without exporting friend classes

Updated:
I created a project that can 100% reproduce the problem.
1. DLL Project
I named this DLL project TestDLL
The most important codes:
AddC.h:
#pragma once
class CTestDLL;
#include <string>
using namespace std;
//use AddC somewhere inside the DLL internally
class AddC{
private:
string _fake_string_ = "_fake_string_";
void _fake_method_();
public:
void add2Result(CTestDLL* test);
};
AddC.cpp:
#include "pch.h"
#include "AddC.h"
#include "TestDLL.h"
void AddC::_fake_method_()
{
_fake_string_ = "_fake_string_in_fake_method_";
}
void AddC::add2Result(CTestDLL * test)
{
test->result += 1;
}
TestDLL.h:
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
#include "AddC.h"
class TESTDLL_API CTestDLL {
public:
CTestDLL(void);
void test();
int getResult();
private:
friend class AddC;
private:
AddC addc;
int result=0;
};
TestDLL.cpp:
#include "pch.h"
#include "framework.h"
#include "TestDLL.h"
CTestDLL::CTestDLL(){
result = 0;
return;
}
void CTestDLL::test(){
auto _this = this;
addc.add2Result(_this);
}
int CTestDLL::getResult(){
return this->result;
}
2. SimpleTestApplication Project
The TestApplication has only two code files.
dll.hpp:
#pragma once
class AddC{};
class CTestDLL {
public:
CTestDLL(void);
void test();
int getResult();
private:
int result = 0;
AddC addc;
};
app.cpp:
#include "dll.hpp"
#include <iostream>
using namespace std;
#pragma comment(lib, "TESTDLL.lib")
int main(){
CTestDLL test;
test.test();
test.test();
test.test();
cout << test.getResult() << endl;
return 0;
}
The testApplication compile and link successfully.
But,But.When the main function exits, the program throws an exception that the stack was corrupted.
The key point is 'fake string_' variable in AddC.
But I don't how to do.
Previous:
Like this on a dll project:
class B;
class C;
class __declspec(dllexport) A{
private:
friend class B;
friend class C;
}
And I compiled the dll project;
Use .dll,.lib and the following header file on a simple console project:
dll.hpp:
class __declspec(dllimport) A{
private:
friend class B;
friend class C;
}
The main func:
#include "dll.hpp"
#pragma comment(lib, "dll.lib")
int main(){
A a;
return 0;
}
It compiled successfully.But the program threw an exception when running:
Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted.
Who can help me?
#selbie's suggestion regarding the factory function / method creating is the cleanest way to go (would prevent you from ending in situations like this), and design-wise it makes the most sense, but it's not mandatory (after all there are lots of .dlls out there exporting classes).
What jumped into my eye, was the fact that (in both scenarios) a header file was present in the application that was (somewhat) duplicating the (main) one in the .dll. Every .dll comes with its own header file(s), and those are the ones that should be used by its clients (apps or other dlls). They are both maintained by the dll creators, and when updates come, they are both in sync. Doing otherwise is not scalable (each app creating its own header file version), makes no sense, and I don't know why would anyone do something like that.
With this in mind, I recreated the environment (both scenarios), doing things the right way, and everything worked fine, then I worked my way to your (wrong) way, trying to identify the culprit.
Example (numbered the 2 scenarios: 00 and 01):
DllExport.h:
#pragma once
#if defined(_WIN32)
# if defined(DLL_STATIC)
# define DLL_EXPORT_API
# else
# if defined(DLL_EXPORTS)
# define DLL_EXPORT_API __declspec(dllexport)
# else
# define DLL_EXPORT_API __declspec(dllimport)
# endif
# endif
#else
# define DLL_EXPORT_API
#endif
Scenario 00:
AddC.hpp:
#pragma once
#include <string>
using namespace std;
class CTestDLL;
//use AddC somewhere inside the DLL internally
class AddC {
private:
string _fake_string_ = "_fake_string_";
void _fake_method_();
public:
void add2Result(CTestDLL *pTest);
};
TestDLL.hpp:
#pragma once
#include <DllExport.h>
#include <AddC.hpp>
class DLL_EXPORT_API CTestDLL {
public:
CTestDLL();
void test();
int getResult();
private:
friend class AddC;
private:
AddC addc;
int result = 0;
};
dll:
AddC.cpp:
#include "AddC.hpp"
#include "TestDLL.hpp"
void AddC::_fake_method_()
{
_fake_string_ = "_fake_string_in_fake_method_";
}
void AddC::add2Result(CTestDLL *pTest)
{
pTest->result += 1;
}
TestDLL.cpp:
#define DLL_EXPORTS
#include <TestDLL.hpp>
CTestDLL::CTestDLL()
{
result = 0;
return;
}
void CTestDLL::test()
{
auto _this = this;
addc.add2Result(_this);
}
int CTestDLL::getResult()
{
return this->result;
}
app:
dll.hpp:
#pragma once
#define _WRONG_INNER_CLASS
#if defined(_WRONG_INNER_CLASS)
class AddC {};
#else
# include <AddC.hpp>
#endif
#define _WRONG_IMPORT_DIRECTIVE
#if defined(_WRONG_IMPORT_DIRECTIVE)
# define CLASS_IMPORT_API
#else
# define CLASS_IMPORT_API __declspec(dllimport)
#endif
class CLASS_IMPORT_API CTestDLL {
public:
CTestDLL();
void test();
int getResult();
private:
int result = 0;
AddC addc;
};
main.cpp:
#include <iostream>
#include <cstdio>
#define _DUPLICATE_DLL_HEADER_FILE
#if defined (_DUPLICATE_DLL_HEADER_FILE)
# include <dll.hpp>
#else
# include <TestDll.hpp>
#endif
#pragma comment(lib, "dll.lib")
using std::cout;
using std::endl;
int main()
{
CTestDLL test;
test.test();
test.test();
test.test();
cout << test.getResult() << endl;
printf("Done.\n");
return 0;
}
Scenario 01:
dll.hpp:
#pragma once
#include <DllExport.h>
class DLL_EXPORT_API A {
private:
friend class B;
friend class C;
};
dll:
dll.cpp:
#define DLL_EXPORTS
class B;
class C;
#include <dll.hpp>
app:
AppDll.hpp:
#pragma once
#define CLASS_IMPORT_API __declspec(dllimport)
class CLASS_IMPORT_API A {
private:
friend class B;
friend class C;
};
main.cpp:
#include <cstdio>
#define _DUPLICATE_DLL_HEADER_FILE
#if defined (_DUPLICATE_DLL_HEADER_FILE)
# include "AppDll.hpp"
#else
# include <dll.hpp>
#endif
#pragma comment(lib, "dll.lib")
int main()
{
A a;
printf("Done.\n");
return 0;
}
Project structure:
Results:
Scenario 00:
There were 2 mistakes:
Class AddC redefinition
Missing import directive for CTestDll
In dll.hpp there are 2 _WRONG* macros. If both are commented, it will work
Scenario 01:
I couldn't reproduce the crash (with / without friends)
Note: Tested with VStudio 2022 and MSSDK 10.0.22000.0

C++ How to prevent Winapi::FreeLibrary removing a variable?

I have a dll with lib.h:
#pragma once
#ifdef EXPORTS
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
extern "C" API void test1(std::vector<ValueType*>* functions);
and lib.cpp:
#include "pch.h"
#include <iostream>
#include <vector>
#include "ValueType.h"
#include "NumberValue.h"
#include "TestLib.h"
void test1(std::vector<ValueType*>* functions) {
functions->push_back(new NumberValue(123321));
And main file, that uses this dll is:
#include <iostream>
#include <vector>
#include <Windows.h>
#include "ValueType.h"
using namespace std;
typedef void (__cdecl* importedInitFunction)(std::vector<ValueType*>*);
importedInitFunction test1F;
std::vector<ValueType*> values;
int main() {
while (1) {
HMODULE lib = LoadLibrary("DllTest1.dll");
test1F = (importedInitFunction)GetProcAddress(lib, "test1");
test1F(&values);
FreeLibrary(lib);
std::cout << values.at(0)->asString();
system("pause");
}
return 0;
}
When I'm trying to compile my code, I catch an error because values.at(0) is removed.
How to prevent deleting my variable when calling FreeLibrary(lib) ? or
How to implement alternative way ?
Another classes that used:
ValueType.h:
#pragma once
#include <string>
class ValueType {
public:
virtual double asDouble() { return 999; }
virtual std::string asString() { return ""; }
};
NumberValue.h:
#pragma once
#include <string>
#include "ValueType.h"
class NumberValue : public ValueType {
public:
double m_value;
NumberValue(double value) : m_value(value) {}
virtual double asDouble() {
return m_value;
}
virtual std::string asString() {
return std::to_string(m_value);
}
};

C++: Warning inconsistent dll linkage

I have an issue with Visual studio (in C++)
I got a warning and I don't know why because I never call 2 time the same variable.
function: inconsistent dll linkage
warning list: (in french)
I read on microsoft: Compiler Warning (level 1) C4273 but I don't really know if it's my problem because the example is not like mine.
I read also About inconsistent dll linkage (StackOverflow and it tell me that because I use MFC in dll but I didn't check the header MFC.
it's my "PayRespectdll.h"
#pragma once
#ifdef PAYRESPECTDLL_EXPORTS
#define PAYRESPECTDLL_API __declspec(dllexport)
#else
#define PAYRESPECTDLL_API __declspec(dllimport)
#endif
#include <ctime>
#include <time.h>
#include <string>
namespace PayRespectDLL
{
class PayRespect
{
private:
static struct std::tm when;
public:
static PAYRESPECTDLL_API bool is_setup();
static PAYRESPECTDLL_API void setup(std::string date);
static PAYRESPECTDLL_API bool is_possible();
}
}
PayRespectDLL.cpp:
// PayRespectDLL.cpp :
//
#include "stdafx.h"
#include "PayRespectDLL.h"
#include <stdexcept>
#include <time.h>
#include <string>
#include <stdlib.h>
using namespace std;
namespace PayRespectdll
{
bool PayRespect::is_setup()
{
return false;//already_setup;
}
// setup attempt String: hh:mm:ss.
void PayRespect::setup(string date)
{
return;
}
bool PayRespect::is_possible()
{
return true;
}
}
thank you!

C++ class name does not name a type

#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
#include "Setup.h"
#include "mainCharacter.h"
class Main {
public:
Main(int pScreenWidth, int pScreenHeight);
~Main();
void gameLoop();
private:
bool quit;
Setup* setup;
mainCharacter* tom;
int screenWidth;
int screenHeight;
int mouseX;
int mouseY;
};
#endif // MAIN_H_INCLUDED
I saw the other topics on this, but the error im getting is not of the same type, how can it tell me that
Setup* setup;
mainCharacter* tom;
does not name a type when the includes are above ?
im using code::blocks if that matters.
EDIT://////////////////////
This is the Setup header:
#ifndef SETUP_H_INCLUDED
#define SETUP_H_INCLUDED
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include "Main.h"
#include "Sprite.h"
class Setup {
public:
Setup(int screenWidth, int screenHeight);
~Setup();
SDL_Renderer* getRenderer();
SDL_Event* getEvent();
private:
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Event* event;
};
#endif // SETUP_H_INCLUDED
and this is the mainCharacter header:
#ifndef MAINCHARACTER_H_INCLUDED
#define MAINCHARACTER_H_INCLUDED
#include "Sprite.h"
#include "Setup.h"
#include <cmath>
class mainCharacter {
public:
mainCharacter(Setup* pSetup, int* pMouseX, int* pMouseY);
~mainCharacter();
double getDistance(int x1, int y1, int x2, int y2);
void update();
void draw();
private:
Sprite* shagy;
///some variables are here/////
Setup* setup;
};
#endif // MAINCHARACTER_H_INCLUDED
there are Setup.cpp and mainCharacter.cpp files and they got a long code written on them, the only thing i inclue in setup.cpp is setup.h and maincharacter.cpp i only include maincharacter.h
#ifndef SETUP_H_INCLUDED
#define SETUP_H_INCLUDED
Make sure you aren't defining SETUP_H_INCLUDED somewhere else, this is the only reason i see.
Also it's possible that your %INCLUDE% (include directories) has another Setup.h somewhere, which does not define Setup class, and your Setup.h is not loaded.

Expected initializer before * token

So I have this header file:
#pragma once
#include "engine.hpp"
namespace spacecubes
{
extern engine* _engine;
}
and the included engine.hpp:
#pragma once
#include <iostream>
#include "glinclude.hpp"
#include "debug.hpp"
#include "convert.hpp"
#include "renderer.hpp"
#include "global.hpp"
namespace spacecubes {
void display();
class engine {
renderer renderengine;
public:
void start(int argc, char* argv[]);
void stop(int status = 0);
void poll();
renderer getRenderEngine() {return renderengine;}
};
}
What the compiler reported later on was:
g++ -c -o bin/obj/engine.o src/engine.cpp
In file included from src/engine.hpp:9,
from src/engine.cpp:1:
src/global.hpp:7: error: expected initializer before '*' token
src/engine.cpp: In function 'void spacecubes::display()':
src/engine.cpp:5: error: '_engine' was not declared in this scope
I don't get it. What did it mean that it expected an init? Thanks in advance!
Replace
#include "engine.hpp"
with a forward declaration:
namespace spacecubes { class engine; }