luabind not making changes to pointer mingw - c++

I have fixed the linker errors I had in this question, but now I am having another problem. I create my objects by calling createObject() in lua and that creates a boost::shared_ptr to a new object, adds it to a list, and returns it.
On windows with mingw when I make changes in lua the changes do not get applied to the C++ object. it cannot be a problem with my code because I built the same thing on Linux and it worked fine.
ObjectPtr createObject(PlayerPtr player){
ObjectPtr obj(new Object(player));
window->world.objects.push_back(obj);
return obj;
}
bool setup(lua_State* luastate, Window* caller){
open(luastate);
// initialize some other classes here.
class_<Player, PlayerPtr> Player("Player");
Player.def_readwrite("playerColor", &Player::playerColor);
Player.def_readwrite("displayName", &Player::displayName);
class_<Object, ObjectPtr> Object("WorldObject");
Object.def_readwrite("health", &Object::health);
Object.def_readwrite("maxHealth", &Object::maxHealth);
Object.def_readwrite("mesh", &Object::mesh);
Object.def_readwrite("location", &Object::location);
Object.property("player", &Object::getPlayer, &Object::setPlayer);
Object.def("setOnDeath", &Object::setOnDeath);
module(luastate)[
vec3,
color,
Player,
WorldObject,
def("isWindowOpen", &isWindowOpen),
def("loadMesh", &MeshManager::LoadMesh),
def("createObject", &createObject),
def("createPlayer", &createPlayer),
];
window = caller;
}
ObjectPtr and PlayerPtr are boost::shared_ptr of Object and Player, window is a static Window pointer, and createPlayer() is the same as createObject() without any arguments and using Player instead of Object.
in lua:
red = createPlayer()
red.playerColor = Color(255,0,0)
red.displayName = "Red"
obj = createObject(red)
obj.location = vec3(10,10,0)
print(obj.player.displayName)
results in "Red" being put in the console.
but in C++ the value is just "".
I debugged it and the objects do get created and added to the list in C++, but no changes were ever made, as all variables are in there default state.
I think it is a problem with luabind and mingw, or just something wrong with the build,
the only things I changed from the default build setup were 2 things I needed to do to get it to compile at all: I set LUA_PATH in the jamfile to point to the directory lua is in (rather than getting it from an environmental variable) and I changed
#elif BOOST_PP_ITERATION_FLAGS() == 1
to
#else
#if BOOST_PP_ITERATION_FLAGS() == 1
because mingw did not like the ( for some reason... (and yes I did add the #endif in the right place)
UPDATE: I have tried using msvc10 also, and it still has the same problem. I have also tried building it against the same version of boost that is on my Linux. but to no avail.

Related

Exit a gtkmm application properly

I am creating a GUI using Glade, and am able to connect signals to it properly. I am trying to have a button that simply quit the application.
The doc is not very clear on how to do so. On some forums you should do:
Gtk::Main::quit();
Which does exit my application, but with a Segmentation Fault. Apparently I am supposed to call quit() directly from my application, like so:
p_application->quit();
But this returns me the resulting error at compile time:
error: invalid use of member ‘GUI::p_application’ in static member function
Glib::RefPtr<Gtk::Application> p_application;
^
error: from this location
p_application->quit();
^
I created the application using this:
p_application = Gtk::Application::create(argc, argv, "org.app.app");
How should I proceed ?
It looks like you are trying to access the p_application member of your GUI class from a static member function of GUI.
You can't access members from static functions, since there is no instance. Change the function to not be static, or get hold of an instance and access the member on that.
Warning: All the online documentation I could find is for gtkmm-4. If you are stuck using gtkmm-3.0 for Ubuntu, download your own docs from the repository (see below). I've included links to gtkmm-4 documentation in the hopes that they are helpful; use at your own risk.
Here is a working solution for gtkmm-3.0. Compile with:
g++ helloworld.cc -o main `pkg-config --cflags --libs gtkmm-3.0`
Code:
// In file helloworld.cc
// sigc::mem_fun is the important part:
// it lets you turn a member function into a static one (or something).
// I don't really get it.
// I got most of the code here from https://www.gtk.org/docs/language-bindings/cpp
#include <iostream>
#include <sigc++/sigc++.h> // Unnecessary, because the gtkmm modules also include mem_fun.
#include <glibmm/refptr.h> // The wrapper object that Application::create returns.
#include <gtkmm/application.h> // C++ wrapper for C's gtk_main.
#include <gtkmm/button.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window
{
public:
HelloWorld(Glib::RefPtr<Gtk::Application>);
protected:
void on_button_clicked();
Gtk::Button m_button;
Glib::RefPtr<Gtk::Application> app;
};
// Constructor for window class. app should be a pointer to the Application instance you made in main.
HelloWorld::HelloWorld(Glib::RefPtr<Gtk::Application> app)
: m_button("Quit this program") // Sets button label. I have no idea what this syntax is. C++ be whack, yo
{
this->app = app;
// mem_fun does most of the magic. How does it work? idk lol
m_button.signal_clicked().connect(sigc::mem_fun(*this,
&HelloWorld::on_button_clicked));
add(m_button);
m_button.show();
}
void HelloWorld::on_button_clicked()
{
std::cout << "Exiting the program now." << std::endl;
this->app->quit();
std::cout << "Note: Program doesn't actually end until this function finishes." << std::endl;
}
int main (int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld(app);
return app->run(helloworld);
}
My thoughts: I don't really get it?
Gtk::Button.signal_clicked() (reference) returns a Glib::SignalProxy<void()>. SignalProxy (reference) has template <R(T...)>, which I think describes the kind of functions that can be connected--in this case, with a return type void and an empty list () of arguments. SignalProxy.connect() returns something I'll ignore, and accepts either a SlotType& or a SlotType&& (I have no idea what the difference is) where SlotType is sigc::slot<R(T...)>, or in this case sigc::slot<void()>.
sigc::slot<R(T...)> (reference) seems pretty fundamental. It looks like it's just a wrapper that holds a function (presumably, so SignalProxy can store it to be called later when the button is clicked). Up until now, it all makes sense.
The notes on sigc::mem_fun (reference) say that it returns a sigc::mem_functor, which sounds reasonable but mem_functor does not seem to fulfill what SignalProxy.connect() wants: sigc::slot and sigc::mem_functor do not inherit from each other. Baffling. I guess there's some kind of undocumented type coercion going on here? Maybe? The other lead is that mem_fun apparently returns an object of type decltype(auto)? Which I tried reading documentation on, and then they started talking about lvalues and unparenthesized id-expressions, and that's when my eyes glazed over. Looking at the old documentation, there used to be like 70 overloaded versions of mem_fun to do what one version can do now, so I guess decltype is doing its job. But the point is, that's where I gave up.
decltype(auto) and mem_functors are C++ deep-magic. mem_fun does the thing SignalProxy.connect() needs, and that's all I know.
References:
gtkmm-4.0 documentation
glibmm documentation
sigc++ documentation
gdk documentation in c << gtkmm refers to stuff like "GdkEventKey" and enumerations from the header <gdk/gdkkeysyms.h>. I couldn't find a c++ reference for this, or anything like "gdkmm". I think maybe gtkmm just uses the C structs for events directly?
Installing documentation: I'm on Ubuntu, 20.04.3 LTS. You can install html documentation for gtk 3.0 from the repository. Do sudo apt install libgtkmm-3.0-doc libglibmm-2.4-doc libsigc++-2.0-doc. To find out where the index file is for, for example, gtkmm, do dpkg -L libgtkmm-3.0-doc | grep index. sigc++ has multiple index files, two of which are traps. I could not figure out where the documentation for GDK is, possibly because there isn't any in the repository. Use the online stuff instead.

c++ map unreadable in dll unless using an iterator

I am creating a game in c++ using the SDL library.
To keep everything readable and orderly, I make a dll from the actual game program, the menu's program and have only the main program as an executable. In the main program I create a struct that holds all screen information, such as standard colors, the width and height of the screen, fonts and the renderer, window and surface object of the screen. In the main program I initialise one instance of this struct. A pointer to this instance is passed as a parameter to the functions and objects in the dll's.
The colors are defined in a std::map<char*, int>.
To access the colors, one could use something like this:
struct screen{
std::map<char*, Uint32> colors;
}
screen display;
std::pair<char*, Uint32> color;
color.first = "green";
color.second = 0x00FF00;
display.colors.insert(color);
int x = display.colors["green"] //for example
Reading the values in the main executable works fine, but having the screen object passed as a pointer to a function inside a dll, it returns a NULL. As a pointer, I read the value like this:
void function(screen* display){
Uint32 x = display->colors["green"];
}
When doing the following:
std::map<char*, int>::iterator i = display->colors.begin();
while(i->first != "green"){
i++
}
int x = i->second;
There seems to be no problem.
But I want to be able to use the first method in the dll's, since the second method is much less efficient.
Why doesn't the first method work in dll's? and how do I get it to work in the dll's? I use visual studio 2012.
The pointer issue I told you about is probably the reason for your problem. In the executable the string literal "green" has one address, and in the DLL the string-literal "green" has a totally different address. Yes the strings will be equal if you compare them, but the pointers themselves will not be the same, leading to your problem.
The answer is simply to use std::string as the key.
You should question yourself what "green" as a char* points to. Without using the DLL, being just one compilation unit gives "green" a single address which will be reused during the program. So, the pointer is the same when getting and retrieving from the map.
When you compile the DLL, the "green" pointer is a different pointer than the "green" pointer from the main executable, so you cannot retrieve it from the map.

Application(mfc) failing in Release build due to compiler optimization but working fine in debug build

I am facing issue with Release build. Application works fine in Debug build but in release build a pointer initialized to hold object of another class is getting different address allocation and thus causing corruption to its values.
My main application class is K32App
code in K32App.h file
CSheetPrintManager* m_pSheetPrintManager;
CSheetPrintManager* GetSheetPrintManager() { return m_pSheetPrintManager; }
In file K32App.cpp
K32App::K32App()
{
m_pSheetPrintManager= NULL;
}
BOOL K32App::InitInstance()
{
if(!m_pSheetPrintManager)
m_pSheetPrintManager= new CSheetPrintManager();
}
K32App::~K32App()
{
if(m_pSheetPrintManager)
delete(m_pSheetPrintManager)
}
In my file CSheetPrintManager.cpp
void CSheetPrintManager::CSheetPrintManager()
{
//Initialized all member variables to default values.
Init();
}
void CSheetPrintManager::Init()
{
m_nSheetType = SheetIllegalNone; //long
m_sBankEntry.Empty(); //CString
m_bHistorical = FALSE; //BOOL
m_bDebitDetailsSet = FALSE; //BOOL
m_mapRequested.RemoveAll(); // Type CMap<long,long,CString,CString&>
}
During application startup, when it reaches
if(!m_pSheetPrintManager)
CSheetPrintManager= new CSheetPrintManager();
and tries to create object of m_pSheetPrintManager, 'this' pointer inside CSheetPrintManager.cpp shows valid address (0x03768ce0) at breakpoint just at curly brace {, once I step further into CSheetPrintManager.Init(), 'this' gets different location and starts point to another address(0x0000000) and then further moving it starts pointing another location(0x03786ce0) and then on reaching m_mapRequested.RemoveAll();
'this' is pointing some other location.
returning back to main app file C32App.cpp , I get following for 'm_pSheetPrintManager' CXX0030 Error 'expression cannot be evaluated" in Auto window.
and appplication continues to run. See what get when hover mouse of m_pSheetPrintManager (can't post image because need 10 reputations for it :) so linking it)
studio Auto window screenshot
In debug mode, I get m_pSheetPrintManager pointing to same location during all application processing and members always remain properly initialized.
But in Release mode, m_pSheetPrintManager continues to point (address value shown in Auto window) different location. and all member variables of class CSheetPrintManager showing different garbage(Uninitialized) values with each line of processing inside CSheetPrintManager Class.
If I disable C++ compiler optimization in Release-Mode then it works fine without any issue.
Any help/guidance/suggestion is most appreciated.
Thanks in advance.
PS: This is my first question here so please excuse in case missing something to point or express properly.
You need to provide more info: Is CSheetPrintManager capsuled in a dll? How does the declaration look? This way I only can play guessing games... :-/
Consider to derive from CObject and use DECLARE DYNCREATE and IMPLEMENT_DYNCREATE for your CSheetPrintManagerclass. You can then VERIFY()in your Release version if it's a valid object using CObject::IsKindOf().
Try #pragma pack() to define how padding is done in your class, especially if you optimized for size in the Release version and having mixed-up Debug and Release dlls.

C++ cocos2d-x pointer

I've just used cocos2d-x for creating some games. When I read the HelloWorld.cpp, I saw this line
Scene* HelloWorld::createScene()
That's strange for me. How does it work? A method named creatScene that takes no parameters and returns a pointer to a Scene ?
In different libraries, there are different methods to initialize library or some part of that. So, in this case, it maybe create a new context inside library and return it without any argument. It maybe needs no arguments (use defaults) it this step of get them from somewhere else like configuration file. And note that this is convenient to use this type of initializing. Like this:
rc = redis.Redis() #uses default values for server address
It is really an easy question even it cannot be called as question when you check the source code.
In cocos2d-x, CCScene always create this way.
1. create a Layer, which coded by yourself with a lot of other widgets.
2. create a Scene
3. add the layer to the scene
4. return the scene you create.

ActiveX plugin causes ASSERT to fail on application exit in VS2008

My MFC application using the "ESRI MapObjects LT2" ActiveX plugin throws an ASSERT at me when closing it.
The error occurs in cmdtarg.cpp:
CCmdTarget::~CCmdTarget()
{
#ifndef _AFX_NO_OLE_SUPPORT
if (m_xDispatch.m_vtbl != 0)
((COleDispatchImpl*)&m_xDispatch)->Disconnect();
ASSERT(m_dwRef <= 1); //<--- Fails because m_dwRef is 3
#endif
m_pModuleState = NULL;
}
I built the (native C++) application with VC9.
When I compile the application with VC6, it behaves nicely.
What could be the reason for this?
That looks like a reference count. Could this "target" be referenced by something else, something that's not releasing it?
You can trace the Addref and Release calls defining _ATL_DEBUG_INTERFACES
from http://msdn.microsoft.com/en-us/library/sycfy8ec(VS.80).aspx
_ATL_DEBUG_INTERFACES
Define this macro before including any ATL header files to trace all AddRef and Release calls on your components' interfaces to the output window.
Using _ATL_DEBUG_INTERFACES did not yield any additional output...
I defined it on the first line of stdafx.h, directly after #pragma once so I guess this is early enough.
Maybe the reason is how I am using the ActiveX control:
I'm not calling AddRef() or Release() by myself.
The MapObjects Installer comes with sample code with lots of wrapper classes which must have been generated by VC6 or something earlier.
I tried to generate wrapper classes myself with VC9 but there occured errors which I wasn't able to fix.
I use the control by letting one of my windows have a member of type CMap1 (derived from CWnd), which is one of those generated wrapper classes. In CMyWnd::OnCreate() I also call CMap1::Create() and that's it, I'm finished: I can add a layer and the control displays a world map.
I have pretty much no idea what the reference-count stuff is about as I have not added or released any references. At least not knowingly...
The control is pretty old: The .OCX file has the year 2000 in its version information.
It's also not officially supported anymore but I don't have any substitue.
The following solved it for me:
In the window that contains the control, add an OnDestroy() handler:
void CMyWnd::OnDestroy()
{
// Apparently we have to disconnect the (ActiveX) Map control manually
// with this undocumented method.
COleControlSite* pSite = GetOleControlSite(MY_DIALOG_CONTROL_ID);
if(NULL != pSite)
{
pSite->ExternalDisconnect();
}
CWnd::OnDestroy();
}