How do I decouple C++ project header dependencies? - c++

"Platform" is a C++ DLL project that includes SDL2. The project is configured with SDL2 includes and library directories. "Sample" is a console application that includes and links to "Platform", but makes no reference to SDL2 whatsoever; other than that implicitly made by my including a thing that includes that library. "Sample" fails to compile on a cpp file in "Platform" with the error that it cannot find SDL2's header files.
I can add the SDL2 include directory to the "Sample" project, but this creates a coupling that seems to defeat the reason I have separated "Platform" from "Sample" in the first place. I looked into precompiled headers, but that seems to solve a different problem; and I couldn't figure out how to get "Sample" to include the "Platform" PCH anyway.
error:
Severity Code Description Project File Line Suppression State
Error C1083 Cannot open include file: 'SDL.h': No such file or directory Sample C:\Users\danie\Source\SingleScreen\Platform\display.h 6
sample.cpp:
#include "platform.h"
int main(int argc, char** argv)
{
Display_Configuration* display_configuration = new Display_Configuration();
display_configuration->window_title = "Sandbox";
display_configuration->dimension_x = 1280;
display_configuration->dimension_y = 720;
display_configuration->color_depth = 24;
display_configuration->is_fullscreen = false;
Platform* platform = new Platform(display_configuration);
return 0;
}
platform.h:
#ifndef SINGLESCREEN_PLATFORM_PLATFORM_H
#define SINGLESCREEN_PLATFORM_PLATFORM_H
#ifdef PLATFORM_EXPORTS
#define PLATFORM_API __declspec(dllexport)
#else
#define PLATFORM_API __declspec(dllimport)
#endif
#include "display.h"
#include "controller.h"
#include "synthesizer.h"
#include "sampler.h"
extern PLATFORM_API class Platform
{
private:
Display* _display;
Controller* _controller;
Synthesizer* _synthesizer;
Sampler* _sampler;
public:
Platform(Display_Configuration* display_configuration);
~Platform();
};
#endif //SINGLESCREEN_PLATFORM_PLATFORM_H
platform.cpp:
#include "pch.h"
#include "platform.h"
Platform::Platform(Display_Configuration* display_configuration)
{
_display = new Display(display_configuration);
_controller = new Controller();
_synthesizer = new Synthesizer();
_sampler = new Sampler();
}
Platform::~Platform()
{
delete _display;
delete _controller;
delete _synthesizer;
delete _sampler;
}
display.h:
#ifndef SINGLESCREEN_PLATFORM_DISPLAY_H
#define SINGLESCREEN_PLATFORM_DISPLAY_H
#include <vector>
#include <string>
#include "SDL.h"
struct Display_Configuration
{
std::string window_title;
bool is_fullscreen;
int dimension_x;
int dimension_y;
int color_depth;
};
class Display
{
private:
std::string _window_title;
bool _is_fullscreen;
int _dimension_x;
int _dimension_y;
int _color_depth;
SDL_Window* _window;
SDL_Surface* _surface;
public:
Display(Display_Configuration* display_configuration);
~Display();
bool initialize();
};
#endif //SINGLESCREEN_PLATFORM_DISPLAY_H
display.cpp:
#include "pch.h"
#include <iostream>
#include "display.h"
Display::Display(Display_Configuration* display_configuration)
{
_window_title = display_configuration->window_title;
_is_fullscreen = display_configuration->is_fullscreen;
_dimension_x = display_configuration->dimension_x;
_dimension_y = display_configuration->dimension_y;
_color_depth = display_configuration->color_depth;
}
Display::~Display()
{
}
bool Display::initialize()
{
_window = NULL;
_surface = NULL;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "Failed to initialize the video subsystem. The error was:" << std::endl << SDL_GetError() << std::endl;
return false;
}
_window = SDL_CreateWindow(
_window_title.c_str(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
_dimension_x, _dimension_y,
SDL_WINDOW_SHOWN | ( _is_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : NULL )
);
if (_window == NULL) {
std::cout << "Failed to create a rendering window. The error was:" << std::endl << SDL_GetError() << std:: endl;
return false;
}
_surface = SDL_GetWindowSurface(_window);
if (_surface == NULL) {
std::cout << "Failed to create a rendering surface. The error was:" << std::endl << SDL_GetError() << std::endl;
return false;
}
return true;
}

TL;DR:
move the include from the header into the source
forward declare SDL_Window and SDL_Surface
Judging by your profile, you recently decided to learn programming. Don't worry, that's cool and you'll figure it out.
Why do I think so? It took me a moment to understand your question because [Y]ou seem at a loss for the right words.
What you are asking for is how to hide implementation details properly in C++. As far as I understood, you're working on a library using SDL under the hood. And you wish to use this library in applications, that do not use SDL directly.
Don't worry, you can achieve that. You just need to fix two things:
Remove the line #include "SDL.h" from any public header and put the line into your cpp-files, that require it. Headers are considered public, if they're meant to be used by another target, like your sample.
Forward declare SDL's types.
Forward wat?
Compilers are of such nature, that they want to know everything. If they don't get that, you'll get slapped with compilation errors.
When it comes to types such as SDL_Window, the compiler wants to know:
Does it exist?
How big is the type?
What attributes does it have?
Which methods does it provide?
Luckily, we can tell the nosy compiler to mind its own business by using so called "forward declarations". I forward declaration looks like this:
// Example for your Display class.
class Display;
// Example for SDL
struct SDL_Window;
struct SDL_Surface;
Using forward declarations we make a promise, that the types Display, SDL_Window and SDL_Surface exist, without including their headers, and they'll be defined somewhere else.
This allows us to store pointers (or references) to instances of those types. This way the include #include "SDL.h" can be moved from the header display.h to the source display.cpp. Your sample wouldn't need to know about SDL's whereabouts.
IMPORTANT! Types that were forward declared cannot be used without definition.
Let's look say you forward declared your own class display in a file; i.e. like this:
class display;
int main() {
auto size = sizeof(display); // Nope!
auto ptr = new display{}; // Nope!
ptr->initialize(); // Nope!
display object_from_somewhere_else;
display* ptr2 = &object_from_somewhere_else; // Yes!
return 0;
};
In order to make a type useable again, we need to include the header that defines the type.
class display;
#include "display.h"
or
#include "display.h"
class display;
int main() {
auto size = sizeof(display); // Yes!
auto ptr = new display{}; // Yes!
ptr->initialize(); // Yes!
display object_from_somewhere_else;
display* ptr2 = &object_from_somewhere_else; // Yes!
return 0;
};
I know this might be a lot to for once. Just bear with me one more moment and let's take a look at how the final result would look like:
display.h
#ifndef SINGLESCREEN_PLATFORM_DISPLAY_H
#define SINGLESCREEN_PLATFORM_DISPLAY_H
#include <vector>
#include <string>
struct SDL_Window;
struct SDL_Surface;
struct Display_Configuration
{
std::string window_title;
bool is_fullscreen;
int dimension_x;
int dimension_y;
int color_depth;
};
class Display
{
private:
std::string _window_title;
bool _is_fullscreen;
int _dimension_x;
int _dimension_y;
int _color_depth;
SDL_Window* _window;
SDL_Surface* _surface;
public:
Display(Display_Configuration* display_configuration);
~Display();
bool initialize();
};
#endif //SINGLESCREEN_PLATFORM_DISPLAY_H
display.cpp
#include "pch.h"
#include <iostream>
#include "display.h"
#include "SDL.h"
Display::Display(Display_Configuration* display_configuration)
{
_window_title = display_configuration->window_title;
_is_fullscreen = display_configuration->is_fullscreen;
_dimension_x = display_configuration->dimension_x;
_dimension_y = display_configuration->dimension_y;
_color_depth = display_configuration->color_depth;
}
Display::~Display()
{
}
bool Display::initialize()
{
_window = NULL;
_surface = NULL;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "Failed to initialize the video subsystem. The error was:" << std::endl << SDL_GetError() << std::endl;
return false;
}
_window = SDL_CreateWindow(
_window_title.c_str(),
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
_dimension_x, _dimension_y,
SDL_WINDOW_SHOWN | ( _is_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : NULL )
);
if (_window == NULL) {
std::cout << "Failed to create a rendering window. The error was:" << std::endl << SDL_GetError() << std:: endl;
return false;
}
_surface = SDL_GetWindowSurface(_window);
if (_surface == NULL) {
std::cout << "Failed to create a rendering surface. The error was:" << std::endl << SDL_GetError() << std::endl;
return false;
}
return true;
}

Related

No sound when using SDL_Mixer in C++/Linux

I'm trying to use SDL_mixer in C++ under Linux to play sounds asynchronously, but it somehow doesn't work. When I execute it, no sound is playing at all. I'm not quite familiar with SDL and classes though, so it would be very helpful if someone could detect where the error in my code is.
My header file (sample.h):
#pragma once
#include <string>
#include <memory>
#include "SDL_mixer.h"
class sample {
public:
sample(const std::string &path, int volume);
void play();
void play(int times);
void set_volume(int volume);
private:
std::unique_ptr<Mix_Chunk, void (*)(Mix_Chunk *)> chunk;
};
My main program (.cpp):
#include "sample.h"
#include <iostream>
sample::sample(const std::string &path, int volume) : chunk(Mix_LoadWAV(path.c_str()), Mix_FreeChunk) {
if (!chunk.get()) {
std::cout << "Could not load audio sample: " << path << std::endl;
}
Mix_VolumeChunk(chunk.get(), volume);
}
void sample::play() {
Mix_PlayChannel(-1, chunk.get(), 0);
}
void sample::play(int times) {
Mix_PlayChannel(-1, chunk.get(), times - 1);
}
void sample::set_volume(int volume) {
Mix_VolumeChunk(chunk.get(), volume);
}
int main() {
if (Mix_Init(MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_OGG) < 0) {
return -1;
}
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) < 0) {
std::cout << "Can not initialize mixer!" << std::endl;
return -1;
}
// Amount of channels (Max amount of sounds playing at the same time)
Mix_AllocateChannels(32);
sample s("Snare-Drum-1.wav", MIX_MAX_VOLUME / 2);
s.play();
Mix_Quit();
return 0;
}
Your binary runs and finishes before phaffing about long enough to render the audio so solution is to make the code remain running longer ... I got your code working by adding this
s.play();
std::chrono::milliseconds timespan(2000); // or whatever
std::this_thread::sleep_for(timespan);
in your header replace
#include "SDL_mixer.h"
with
#include <SDL2/SDL_mixer.h>
#include <chrono>
#include <thread>
so now its compiled using SDL2 and not SDL
g++ -o sample sample.cpp -lSDL2 -lSDL2_mixer
So .... what is the real SDL2 solution ? well I would say a typical use case is SDL2 is part of a game which remains running hence the code base has an event loop which remains active long enough to hear the audio getting rendered. Another solution short of explicitly using a sleep or a gui is to put the code into a server ... SDL2 api itself must have their one-liner as well

Handle threads between classes with C++, libvlc and ubuntu

I have an application in C++ with a GUI interface that needs to reproduce some mp3 depending on user's interactions. I need to reproduce the mp3 without blocking the program's flow.
In order to save code, I decided to write a class to handle the mp3 reproducing and to reproduce it in a new thread, but I'm having problems when I need to stop the playing.
I know that libvlc have already some locking function, but the flow of the program stops when the mp3 is playing.
The mp3 starts correctly, but if I try to call the stop_mp3() function, I get a core dumped error.
The error is generated when I call the stop function from the secondpanel.cpp.
// replay.h
#include <vlc/vlc.h>
class rePlay
{
public:
rePlay();
virtual ~rePlay();
void play_mp3(const char*);
void stop_mp3();
protected:
libvlc_instance_t *inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
private:
};
// rePlay.cpp
#include "rePlay.h"
#include <vlc/vlc.h>
#include <mutex>
std::mutex mp3_mutex;
rePlay::rePlay()
{
//ctor
}
rePlay::~rePlay()
{
//dtor
}
void rePlay::play_mp3(const char* path){
mp3_mutex.lock();
// load the vlc engine
inst = libvlc_new(0, NULL);
printf("apro il file %d\n", inst);
// create a new item
m = libvlc_media_new_path(inst, path);
// create a media play playing environment
mp = libvlc_media_player_new_from_media(m);
// no need to keep the media now
libvlc_media_release(m);
// play the media_player
libvlc_media_player_play(mp);
printf("Done.\n");
}
void rePlay::stop_mp3(){
mp3_mutex.unlock();
// stop playing
libvlc_media_player_stop(mp);
// free the media_player
libvlc_media_player_release(mp);
libvlc_release(inst);
}
// firstpanel.h
class firstpanel: public wxPanel
{
public:
firstpanel(wxWindow* parent, Isola02Frame*, wxWindowID id=wxID_ANY,const wxPoint& pos=wxDefaultPosition,const wxSize& size=wxDefaultSize);
virtual ~firstpanel();
void checkValue(wxCommandEvent& event);
void check_cf(wxTimerEvent& event);
rePlay *mp3_apertura_porta = new rePlay(); // <-- I DECLARED THE pointer here
//(*Declarations(firstpanel)
wxStaticText* assistenza;
wxStaticText* first_panel;
wxStaticText* identificazione;
wxTextCtrl* tessera;
//*)
...
}
// firstpanel.cpp
std::thread second = std::thread([this]() noexcept {
this->mp3_apertura_porta->play_mp3("/home/robodyne/Project/audio/scegli-rifiuto.mp3"); });
second.join();
// secondpanel.cpp
void secondpanel::OnBitmapButton2Click(wxCommandEvent& event)
{
firstpanel *ptr;
ptr->mp3_apertura_porta->stop_mp3();
}
EDIT1: Thanks to #Ted Lyngmo, I used the libvlcpp library which seems to be async somehow and it works fine. The only problem is that I do not know how to call mp.stopAsync() from stop_mp3() to stop the audio file because variable mp is not global.
#include "rePlay.h"
#include <vlc/vlc.h>
#include <mutex>
#include <unistd.h>
#include "vlcpp/vlc.hpp"
std::mutex mp3_mutex;
rePlay::rePlay()
{
//ctor
}
rePlay::~rePlay()
{
//dtor
}
void rePlay::play_mp3(const char* path){
auto instance = VLC::Instance(0, nullptr);
auto media = VLC::Media(instance, path, VLC::Media::FromPath);
auto mp = VLC::MediaPlayer(media);
auto mp.play();
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
#else
mp.stop();
#endif
}
void rePlay::stop_mp3(){
mp.stopAsync(); <-- variable mp is not global!
}
EDIT2:
I think the libvlcpp doesn't work well with GUI applications.
If I run it in a console application, I'm able to perform other operations in parallel, but when I execute it in the WxWidgets application, it blocks the flow.
This is the terminal console application:
#include "vlcpp/vlc.hpp"
#include <thread>
#include <iostream>
int main(int ac, char** av)
{
if (ac < 2)
{
std::cerr << "usage: " << av[0] << " <file to play>" << std::endl;
return 1;
}
auto instance = VLC::Instance(0, nullptr);
auto media = VLC::Media(instance, av[1], VLC::Media::FromPath);
auto mp = VLC::MediaPlayer(media);
mp.play();
for (int i=0; i < 10000000; i++){
printf("%d\n", i);
}
std::this_thread::sleep_for( std::chrono::seconds( 10 ) );
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
mp.stopAsync();
#else
mp.stop();
#endif
}
the for() cycle works in parallel while the mp3 is playing.
The same doesn't happen if I use it with my application.

Why do I get error C2143 syntax error: missing ';' before '*'?

I get the following errors:
Severity Code Description Project File Line Suppression State
Error C2143 syntax error: missing ';' before '*' flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
Severity Code Description Project File Line Suppression State
Error C4430 missing type specifier - int assumed. Note: C++ does not
support
default-int flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
Severity Code Description Project File Line Suppression State
Error C2238 unexpected token(s) preceding
';' flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
This is my header flashlight.hpp file:
#ifndef FLASHLIGHT_H
#define FLASHLIGHT_H
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>
#include "orbslam3.hpp"
using boost::asio::ip::udp;
class Flashlight {
public:
Flashlight(boost::asio::io_service& io_service, short port) : io_service_(io_service), socket_(io_service, udp::endpoint(udp::v4(), port)) {
// start receiving udp data
socket_.async_receive_from(
boost::asio::buffer(data_recv_, max_length), sender_endpoint_, boost::bind(&Flashlight::handle_receive_from, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
void start_loop();
void send_beacon();
void handle_send_to(const boost::system::error_code& error, size_t bytes_sent);
void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
private:
ORBSLAM3 *orbslam; // <= ERRORS APPEAR HERE (Line 36)
boost::asio::io_service& io_service_;
udp::socket socket_;
udp::endpoint sender_endpoint_;
enum { max_length = 1024 };
char data_recv_[max_length];
char data_sent_[max_length];
};
#endif
And this is my implementation file flashlight.cpp:
#include "flashlight.hpp"
using namespace std; // for atoi()
using boost::asio::ip::udp;
int main(int argc, char* argv[]) {
try {
const uint16_t udp_port = 19630;
// thread to run network services asynchronously
boost::thread_group tgroup;
// start udp network endpoint
boost::asio::io_service io_service;
// instantiate flashlight class
Flashlight flashlight(io_service, udp_port);
// run network entities in own thread
tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
cout << "Server running on UDP port " << udp_port << endl;
// start main loop
flashlight.start_loop();
// shutdown network threads
tgroup.join_all();
} catch(exception& e) {
cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
void Flashlight::start_loop() {
string sensor_type = "stereo";
string vocab_path = "D:\\Flashlight\\ORBSLAM3\\Examples\\Monocular\\Release\\ORBVoc.bin";
string settings_path = "D:\\Flashlight\\ORBSLAM3\\Examples\\Monocular\\Release\\stereo_2_8_mm_640_480.yaml";
//const string settings_path = "../"+sensor_type+"_"+lens_type+"_mm_"+to_string(cam_width)+"_"+to_string(cam_height)+".yaml";
uint16_t cam_width = 640;
uint16_t cam_height = 480;
// orb slam system initialization
this->orbslam = new ORBSLAM3(sensor_type, vocab_path, settings_path, cam_width, cam_height);
// mainloop
char key;
while((key = std::cin.get()) != 27) {
this->orbslam->loop();
}
// shutdown orbslam threads
this->orbslam->shutdown();
// save camera trajectory
//orbslam->SaveTrajectoryTUM("CameraTrajectory.txt");
}
void Flashlight::send_beacon() {
while(true) {
boost::posix_time::seconds workTime(1);
// send_async(beacon)
std::cout << "Beacon signal sent ..." << std::endl;
boost::this_thread::sleep(workTime);
}
}
void Flashlight::handle_receive_from(const boost::system::error_code& error, size_t bytes_recv) {
if(!error && bytes_recv > 0) {
std::cout << "UDP received: "; for(int i=0; i<bytes_recv; i++) std::cout << (int)data_recv_[i] << ", "; std::cout << std::endl;
// start listening again
socket_.async_receive_from(
boost::asio::buffer(data_recv_, max_length), sender_endpoint_, boost::bind(&Flashlight::handle_receive_from, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
}
void Flashlight::handle_send_to(const boost::system::error_code& error, size_t bytes_sent) {
socket_.async_send_to(
boost::asio::buffer(data_sent_, bytes_sent), sender_endpoint_, boost::bind(&Flashlight::handle_send_to, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
I can't spot what I am missing. Some idea?
UPDATE: added orbslam3.hpp and orbslam3.cpp
#ifndef ORBSLAM3_H
#define ORBSLAM3_H
#include <algorithm>
#include <fstream>
#include <chrono>
#include <opencv2/core/core.hpp>
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>
#include "flashlight.hpp"
// ==============================
// IMPORTANT: Don NOT move up the
// ========== following include !
#include <System.h>
class ORBSLAM3 {
public:
ORBSLAM3(string &sensor_type, string &vocab_path, string &settings_path, uint16_t cam_width, uint16_t cam_height);
int loop();
void pause();
void resume();
void reset();
void setMode(bool mapping); // false := localization only, true := localization+mapping
void saveMap();
void loadMap();
void shutdown();
private:
string sensor_type; // types = {"mono", "stereo", "rgbd")
string vocab_path; // path to the vocabulary (*.bin/*.txt)
string settings_path; // patch to the settings file (*.yaml)
uint16_t cam_width; // horizontal camera resolution
uint16_t cam_height; // vertical camera resolution
ORB_SLAM2::System *slam; // main orbslam system
cv::VideoCapture *cap1; // first camera capture devices
cv::VideoCapture *cap2; // second camera capture devices
cv::Mat img_left, img_right; // stereo images captured
cv::Mat tcw; // pose output information
};
#endif
And the implementation file orbslam3.cpp:
#include "orbslam3.hpp"
using namespace std;
ORBSLAM3::ORBSLAM3(string &sensor_type, string &vocab_path, string &settings_path, uint16_t cam_width, uint16_t cam_height) {
// assign arguments to local fields
this->sensor_type = sensor_type;
this->vocab_path = vocab_path;
this->settings_path = settings_path;
this->cam_width = cam_width;
this->cam_height = cam_height;
// initialize ORBSLAM system
if(sensor_type.compare("mono")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::MONOCULAR, true, true);
} else if(sensor_type.compare("stereo")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::STEREO, true, true);
} else if(sensor_type.compare("rgbd")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::RGBD, true, true);
} else {
std::cout << "ERROR: Unknown sensor type: " << sensor_type << std::endl;
}
// initialize cameras
cap1 = new cv::VideoCapture(0);
cap2 = new cv::VideoCapture(1);
// set camera resolutions
cap1->set(CV_CAP_PROP_FRAME_WIDTH, cam_width);
cap1->set(CV_CAP_PROP_FRAME_HEIGHT, cam_height);
cap2->set(CV_CAP_PROP_FRAME_WIDTH, cam_width);
cap2->set(CV_CAP_PROP_FRAME_HEIGHT, cam_height);
}
int ORBSLAM3::loop() {
// capture left and right images
cap1->read(img_right);
cap2->read(img_left);
// convert to b/w
//cv::cvtColor(imRight, imRight, CV_BGR2GRAY);
//cv::cvtColor(imLeft, imLeft, CV_BGR2GRAY);
// check image validity
if(img_left.empty()) {
cerr << endl << "Failed to capture left image." << endl;
return 1;
}
if(img_right.empty()) {
cerr << endl << "Failed to capture right image." << endl;
return 1;
}
// time
__int64 cnow = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// pass the images to the SLAM system
tcw = slam->TrackStereo(img_left, img_right, cnow / 1000.0);
// visualize stereo images
cv::imshow("Left Image", img_left);
cv::imshow("Right Image", img_right);
}
void ORBSLAM3::pause() {
}
void ORBSLAM3::resume() {
}
void ORBSLAM3::reset() {
}
void ORBSLAM3::setMode(bool mapping) {
}
void ORBSLAM3::saveMap() {
}
void ORBSLAM3::loadMap() {
}
void ORBSLAM3::shutdown() {
slam->Shutdown();
cap1->release();
cap2->release();
}
Looks like you have a circular dependency.
Fix that and it should work.
flashlight.hpp
// Remove this line.
// #include "orbslam3.hpp"
// Add a forward declaration.
// Unless you need the full declaration you should not be including the header file
// Prefer to use forward declarations when you are just using a pointer.
class ORBSLAM3;
flashlight.cpp
#include "flashlight.hpp"
// Add this line.
// You will probably need the actual definition if you use it in the code.
#include "orbslam3.hpp"
orbslam3.hpp
// Does not even look you need this in the header file.
// Remove headers you don't need.
// #include "flashlight.hpp"

LoadLibrary : crash in release mode [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I use the function LoadLibrary from the Windows API to load dynamically a DLL (compiled in release mode). Then I call an imported function my_function
When my exe is compiled in:
DEBUG mode: no issue
RELEASE mode w/ debug info: no issue
RELEASE mode w/out debug info: it crashes after LoadLibrary call, when I call the imported function my_function
Here's a code sample:
MyClass.cpp:
#include "myclass.h"
typedef int (__stdcall *f_my_function)(char*, int*);
MyClass::MyClass()
{
mDllHandler = NULL;
}
bool MyClass::loadLibrary()
{
qCritical() << "Loading library";
mDllHandler = LoadLibrary(L"my.dll");
qCritical() << "Library loaded";
if (!mDllHandler) {
qCritical() << "Error : could not load my.dll";
return false;
}
return true;
}
bool MyClass::freeLibrary()
{
if(!mDllHandler) {
qCritical() << "Error : DLL handler is null";
return false;
}
if(!FreeLibrary(mDllHandler)) {
qCritical() << "Error : could not unload my.dll";
return false;
}
mDllHandler = NULL;
return true;
}
bool MyClass::myFunction(const& QString str)
{
if(!mDllHandler) {
qCritical() << "Error : DLL handler is null";
return false;
}
f_my_function my_function = (f_my_function)GetProcAddress(mDllHandler, "my_function");
if (!my_function) {
qCritical() << "Error : Could not resolve the function my_function";
return false;
}
int size = str.size();
char* string = str.toLatin1().data();
int error = my_function(string, &size);
qDebug() << "my_function : Error code is " << error;
return !error;
}
MyClass.h:
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QString>
class MyClass
{
public:
MyClass();
bool loadLibrary();
bool freeLibrary();
bool myFunction(const QString& str = "");
private:
HINSTANCE mDllHandler;
};
#endif // MYCLASS_H
main.cpp
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass myClass;
myClass.loadLibrary();
myClass.myFunction();
myClass.freeLibrary();
return a.exec();
}
I really have no idea why it crashes here.
EDIT : Here I don't have access to the source code of my.dll.
Well the crash (which eventually did not occur always at LoadLibrary call, but sometimes later in the code) was due to a wrong declaration of the imported functions.
In MyClass.cpp :
Wrong declaration:
typedef int (__stdcall *f_my_function)(char*, int*);
Correct declaration:
typedef int (*f_my_function)(char*, int*);
Indeed I wrongly declared f_my_function with __stdcall

header include in main.cpp works, but throws error in class

I had asked this question here. But the problem seems to be something else so re-posting here..
I am including the header <zbar.h> from Zbar library in main.cpp and the sample code works perfectly fine.
#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#include <highgui.h>
#include <cv.h>
using namespace std;
using namespace zbar;
using namespace cv;
int main (int argc, char **argv){
if(argc < 2) return(1);
// create a reader
ImageScanner scanner;
// configure the reader
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
// obtain image data
Magick::Image magick(argv[1]); // read an image file
int width = magick.columns(); // extract dimensions
int height = magick.rows();
Magick::Blob blob; // extract the raw data
magick.modifyImage();
magick.write(&blob, "GRAY", 8);
const void *raw = blob.data();
// wrap image data
Image image(width, height, "Y800", raw, width * height);
// scan the image for barcodes
int n = scanner.scan(image);
cv::Mat dispImage = imread(argv[1]);
// extract results
for(Image::SymbolIterator symbol = image.symbol_begin();
symbol != image.symbol_end();
++symbol) {
// do something useful with results
cout << "decoded " << symbol->get_type_name()
<< " symbol \"" << symbol->get_data() << '"' << endl;
}
}
// clean up
image.set_data(NULL, 0);
return(0);
}
But if I make a dummy class and include zbar.h in the header of this class, I get the following error :
the default argument for parameter 0 of ‘zbar::Exception::Exception(const void*)’ has not yet been parsed line 144, external location: /usr/local/include/zbar/Exception.h C/C++ Problem
#ifndef DUMMY_H
#define DUMMY_H
#include <zbar.h>
class dummy{
public:
dummy();
};
#endif // DUMMY_H
I even tried with
extern "C"{
#include <zbar.h>
}
but it throws 100s of template with C linkage error.
According to this documentation, the constructor is declared as
Exception(const void * = NULL);
The error suggests that NULL hasn't been declared; meaning that nothing has included <cstddef>. You should be able to fix it by including that yourself, before the evil header.