Interfacing with C++, random errors

BlitzMax Forums/BlitzMax Programming/Interfacing with C++, random errors

Htbaa(Posted 2008) [#1]
This is the first time I'm trying to use C++ with BlitzMax. I've been programming in C++ for over a year now.

I've written a small class that'll store some configuration data like screen mode and rendering mode. I used MaxGUI to write an application launcher. The game itself is written in C++. The application launcher loads and saves the configuration data in a file called config.dat. The game will read this configuration file so it can setup according to the users' wishes.

I've read the "manual" about interfacing with C++ and it said that all methods you're going to use need to be virtual. So I did that. I also created a couple of functions to create a new object and to delete it. Just like the help page said.

However, I'm getting random errors. After a configuration file has been saved the launcher application is sometimes having problems loading it. About 10 times it loads the configuration file without error and the correct values are being loaded. However, after some time the file somehow gets corrupted.

If a file can't be loaded the C++ class returns Null. If in BlitzMax I check if the value is Null then I create a new object with default parameters. So if a file can't be loaded, it return Null. However, it does load and doesn't return Null. After being loaded and calling the methods getRenderMode() or setRenderMode() I get segmentation errors. I once got a error much like this "Pure virtual methods"... As if the methods weren't supposed to be virtual?

I would highly appreciate if someone could take a look at it and tell me what could be wrong. I originally intended the properties render_mode and screen_mode to be private. And I still want to do that, if BlitzMax supports it. The properties itself don't have to be accessible as a Field in BlitzMax. I can use my getters and setters for that. If at least these problems stop.

There are 3 files. config.bmx (the BlitzMax glue), config.h and config.cxx:

config.h
#ifndef _2DSUPERSHOOT_CONFIG_H
#define _2DSUPERSHOOT_CONFIG_H
class SSConfig {
	private:
	protected:
	public:
		int render_mode;
		int screen_mode;
		SSConfig();
		virtual ~SSConfig();
		virtual void setScreenMode(int mode);
		virtual void setRenderMode(int mode);
		virtual int getScreenMode();
		virtual int getRenderMode();
		virtual int save(char filename[]);
		static SSConfig* load(char filename[]);
};
#endif


config.cxx
#include "config.h"
#include <fstream>
#include <iostream>
// Constructor
SSConfig::SSConfig() {
	//this->screen_mode = 1;	// Default to full screen
	//this->render_mode = 1;	// Default to OpenGL
}

// Destructor
SSConfig::~SSConfig() {
}

// setter for screen mode
void SSConfig::setScreenMode(int mode) {
	this->screen_mode = mode;
}

// setter for rendering mode
void SSConfig::setRenderMode(int mode) {
	this->render_mode = mode;
}

// getter for screen mode
int SSConfig::getScreenMode() {
	return this->screen_mode;
}

// getter for render mode
int SSConfig::getRenderMode() {
	return this->render_mode;
}


// static method to load a file
SSConfig* SSConfig::load(char filename[]) {
	SSConfig *config = new SSConfig();
	std::ifstream file(filename, std::ios_base::binary);
	if(!file.is_open()) {
		delete config;
		return NULL;
	}

	file.read(reinterpret_cast<char *>(config), sizeof(SSConfig));
	file.close();
	return config;
}

// save configuration to file
int SSConfig::save(char filename[]) {
	std::ofstream file(filename, std::ios_base::binary);
	if(!file.is_open()) {
		return -1;
	}

	file.write(reinterpret_cast<char *>(this), sizeof(SSConfig));
	file.close();
	return 1;
}

// External C functions for use with BlitzMax
extern "C"{
	SSConfig* CreateTSSConfig(){
		return new SSConfig;
	}

	void DestroyTSSConfig( SSConfig *t ){
		delete t;
	}

	SSConfig* LoadTSSConfig(char filename[]){
		return SSConfig::load(filename);
	}
}


config.bmx
SuperStrict
Import "config.cxx"

Extern
	Type TSSConfig
		
		Field screen_mode:Int
		Field render_mode:Int
		
		Method _pad1()
		Method _pad2()
		Method setScreenMode(mode:Int)
		Method setRenderMode(mode:Int)
		Method getScreenMode:Int()
		Method getRenderMode:Int()
		Method save:Int(filename:Byte Ptr)
	End Type
	
	Function CreateTSSConfig:TSSConfig()
	Function DestroyTSSConfig( t:TSSConfig )
	Function LoadTSSConfig:TSSConfig( filename:Byte Ptr )
EndExtern


A simple test:

Local t:TSSConfig = CreateTSSConfig()
t.setRenderMode(1)
t.setScreenMode(1)
t.save("test.dat")
DestroyTSSConfig(t)

Local t:TSSConfig = LoadTSSConfig("test.dat")
Print t.getRenderMode()
Print t.getScreenMode()
DestroyTSSConfig(t)



Htbaa(Posted 2008) [#2]
Some of the errors popping up:

Unhandled Exception: appstub.linux signal handler 11

This one comes in right after I call a method (getRenderMode() or any other) on what seems like a successfully loaded config file. This error pop ups if the configuration file was created and saved within the C++ game.

The weird thing is that I'm able to access its data members. The code below crashes at the 3rd line. But the data that was stored inside the config file is being shown by the first 2 print statements.
Print "Screen mode: " + config.screen_mode
Print "Render mode: " + config.render_mode
Print "Render mode from method: " + config.getRenderMode()


I'm thinking that my BlitzMax glue isn't properly written. Does anyone have an idea?


Brucey(Posted 2008) [#3]
I wouldn't use a Type built on a C++ class.

I'd just get an instance of the C++ object and pass that pointer into functions, which in turn call the C++ class methods.

Doing it your way you are making assumptions that what the docs say you can do, is actually what you can do. :-)


Htbaa(Posted 2008) [#4]
My native language isn't English, so I found your last sentence a bit confusing. Did you meant "can't do"?

I'm not really seeing how the method you're suggesting should be brought into practice. But perhaps that's my lack of BlitzMax knowledge.

Can I return a pointer in BlitzMax that doesn't necessarily describe a type but would still function as the C++ class?


Htbaa(Posted 2008) [#5]
Under Windows XP I get the following error when executing the same code.
Unhandled Memory Exception



Otus(Posted 2008) [#6]
For me your tests work correctly, although you have screen mode and render mode the wrong way around in the code above.



Output:
2
2
1
1

No errors.


Htbaa(Posted 2008) [#7]
Ok thanks. But if the configfile is being saved in a C++ program and then being read in BlitzMax it causes errors.

The save instructions are the same so I don't understand why I can't save a config file in my C++ program. It should be portable.

Is there any chance the garbage collector would mess things up?


update - 25-12-2009
Didn't want to reply to this old topic but needed to share this. I believe these errors had to do with how the compiler aligns the data members of the class. This is for optimization. Luckily you can override this behavior.