Showing posts with label cplusplus

Tomfoolery with Lua

Posted on 2/23/2008 by Glenn

Labels: cplusplus lua programming

I done a fair but of hacking around with the lua scripting language in the past, and while my motives for doing so were oftentimes questionable the fact remains that I learnt a few tricks that make embedding and using it easier.

As a language lua takes a "less is better" approach and instead provides the tools for you to extend its functionality rather than bloating the core distribution with stuff that isn't really necessary. As such you'll need to add some of that bloat yourself :) Henceforth I will be making the dubious assumption that you are familiar with the basics of embedding lua with c++ applications and get right into the meat of things.

Getting a lua stack trace

when a lua script encounters an error you can get the error message from the top of the lua stack by calling

lua_tostring(luaState,-1);


however wouldn't it be more useful to get a full stack trace to give you more context as to where and why the error occurred? Luckily lua includes a nifty mechanism for hooking into events during script execution and while these can be used for all sorts of extremely cool and powerful things, I'll be showing how you can use these events to build a call stack.

firstly lets create a list of strings (we'll be using it as a stack...),a new lua state and hook up some events to it. The lua _sethook function allows you to hook in a number of events and provide a callback function to call when these events occur. In this case we want to be notified whenever a function is called (LUA_MASKCALL) or whenever a function returns (LUA_MASKRET)


std::list<std::string> _stack;
_state = luaL_newstate();
lua_sethook(_state,&FunctionHook,LUA_MASKCALL | LUA_MASKRET,0);

This should allow us to build up a callstack by pushing information on the last called function onto a stack, then popping the top off the stack every time a function returns, simple eh? now on to the implementation of the callback function

void FunctionHook(lua_State *l, lua_Debug *ar)
{


//fill up the debug structure with information from the lua stack

lua_getinfo(l, "Sln", ar);
//push function calls to the top of the callstack
if (ar->event == LUA_HOOKCALL) {

std::stringstream ss;
ss << ar->short_src << ":"

<<
ar->linedefined << ": "
<< (
ar->name == NULL ? "[UNKNOWN]" : ar->name)
<<
" (" << ar->namewhat << ")";

_stack.push_front(ss.str());
}

//pop the returned function from the callstack
else if (ar->event ==LUA_HOOKRET) {

if
(_stack.size()>0)
{

_stack.pop_front();
}
}
}

This function gets automatically called whenever a function is called or a function returns. Each time a call event takes place we push some information regarding that function (name, line number etc...) onto our call stack, and every time a function returns we pop it from the call stack.
So when a lua script encounters an error the contents of the _stack variable will contain a full stack trace up until the point of the error, neat eh? (the cryptic "Sln" parameter for the lua_getinfo function specifies what fields of the lua_Debug struct to populate, see the lua reference manual for more information if you're interested)

NOTE: You'll probably only want to enable this stack tracing for debug builds of your applications as there is a performance hit in hooking into these lua VM events.

At some stage in the future I'll blog about my c++ LuaState class which wraps up the process of creating, loading, running, debugging and cleaning up lua scripts in a nice OO fashion but until then enjoy your new-found stack tracery.
1 Comments

Mapping boost::signals to .net events

Posted on 11/24/2007 by Glenn

Labels: cplusplus programming

A while back I blogged about wrapping native c++ classes inside managed .net classes using c++/cli, and while that blog detailed wrapping up a class with methods and properties I did not go over how to map across boost::signal's to the .net event model.

Below we have a native c++ class which has the ability to copy files and notify listening classes of it's progress in doing so.

Unmanaged Class Interface

class FileCopier
{


public
:
typedef struct
{
long
BytesCount;
long
BytesCopied;
std::string CurrentFile;
}
CopyProgressEvent;

typedef
boost::signal<void (CopyProgressEvent)>

CopyProgressEventHandler;//progress callback signature

/**
add a listener to copy progress events
*/

void
AddCopyProgressListener(
CopyProgressEventHandler::slot_type listener);

private
:
CopyProgressEventHandler _handler;

};

The AddCopyProgressListener class accepts a pointer to a suitable callback function that conforms to the signature void(CopyProgressEvent) and adds that callback to the event handler
which can be used to notify all listeners of the event. All well and good so now to wrap it up in .net goodness using c++/cli. We'll be using the managed wrapper class I wrote in a previous blog entry (here) as the basis for the file copier wrapper.

The full interface for the wrapper class is shown below, in order for this to work we have to duplicate the copyProgressEvent in a managed class and supply our own delegate class and event for managed listeners to subscribe to. The notifyListeners method is what takes an unmanaged copyProgress event, wraps it up in its managed equivalent and passes it off to the event handler

Managed Class Interface
public ref class
ManagedCopyProgressEvent {

public
:
long
BytesCount;
long
BytesCopied;
System::String^ CurrentFile;
};


public ref class
ManagedFileCopier:
ManagedEntityBase<FileCopier>
{

public
:
delegate
void CopyProgressEventHandler(

ManagedCopyProgressEvent^ args);
event
CopyProgressEventHandler^
OnCopyProgress;

ManagedFileCopier();

public private
:
void
NotifyListeners(
CopyProgressEvent args);
};



Okay, so the interface makes sense to any .net classes wanting to subscribe to the copyprogress events, but how are we going to do the behind the scenes routing of the boost::signal event such that notifyListeners gets called at the appropriate times? If we were working with native c++ classes we can happily used boost::bind to turn the notfyListeners member function into a suitable callback for the signals event, however because NotifyListeners is part of a managed class, this approach doesn't work so we have to take a slightly more roundabout approach.

The notifier proxy

This is where the function below comes in. Its purpose is to provide a valid function for boost::bind to use as a callback, but also to keep a reference to our managed class so that NotifyListeners can be called when a boost::signals event is fired (This should hopefully make more sense when we actually hook all these pieces up in the managed classes constructor)

void
NotifyProxy(
gcroot<ManagedFileCopier ^> this_,
CopyProgressEvent args) {

this_->NotifyListeners(args);
}


Putting it all together

The implementation of the constructor is where the notifier proxy gets hooked up to the unmanaged boost signals event. Using boost::bind we use the notifyProxy function and the instance of the managed class to create a callback for the unmanaged boost::signal.
ManagedFileCopier::ManagedFileCopier() :
ManagedEntityBase(new FileCopier(),true) {
NativeEntity->AddCopyProgressListener(

boost::bind(
NotifyProxy,
gcroot<ManagedFileCopier^>(this),

_1)
);
}


The implementation of the NotifyListeners method is pretty straightforward, we create a new instance of a managedCopyProgressEvent then copy the unmanagd attributes over before passing the object as an argument to the .net OnCopyProgress event.

void ManagedFileCopier::NotifyListeners(
CopyProgressEvent args)
{

ManagedCopyProgressEvent^ mArgs =
gcnew
CopyProgressEvent();

mArgs->BytesCopied = args.BytesCopied;
mArgs->BytesCount = args.BytesCount;

OnCopyProgress(mArgs);
}


So there you have it! thats how you can route events from the boost::signals library though to managed .net code. Below is an example of some c# code using the managed class we've written.

ManagedFileCopier fc = new ManagedFileCopier();

fc.OnCopyProgress +=
new ManagedFileCopier.CopyProgressEventHandler(
OnCopyProgress);

void
OnCopyProgress(ManagedCopyProgressEvent args)
{
...
}



UPDATE: you can find the source for this example here
2 Comments

The trip to c++/cli with unexpected results

Posted on 9/16/2007 by Glenn

Labels: cplusplus programming

I recently had reason to want a virtual file system (i.e a wrapper around the physical file system such that various archive files were enumerated as if they were folders for easy navigation and reading of those files) for use in a C# application. Fortunately I had a piece of code which I had already written... except for one small probelm, the entire thing was written in unmanaged c++.

So armed with the meagre knowledge that there was some way to wrap up native assemblies using some manner of managed c++ ( the latest iteration of which is named c++/cli), I headed off into the scary world of .net/native interop to try and save myself a rewrite of all my code.

c++/cli is the only .net language capable of using managed and unmanaged code in a single assembly, so while being extremely powerful its also extremely complicated as you have a superset of both .net and unmanaged c++ features and all the issues with interoping between them all in a single language. To cut the suspense from this tale, I'll say that I was able to wrap up my unmanaged code without (too many) problems, this included mapping across getter/setter methods as properties, boost::signal callbacks as .net delegates and events and managing the memory of my unmanaged objects within thier managed wrappers.

So without further ado, here are a few useful peices of code and patterns that I used to make wrapping unmanaged entities easier.

Pattern the first: mapping strings
While primitive types such as int's and bools can be passed back and forth between managed and unmanaged code with no conversion, c++'s std::string and .net's string classes need to be mapped explicitly.
Mapping to .net strings from c++ is relatively simple and can be accomplished using the code below

std::string nativeStr;
nativeStr = "hello world";
System::String^ ManagedStr =
gcnew
System::String(nativeStr.c_str());

Mapping from c++ back to .NET is a little bit more complicated but can be accomplished with the function below

std::string MarshalString ( System::String^ s)
{

const
char* chars = (const char*)
(
System::Runtime::InteropServices::
Marshal::StringToHGlobalAnsi(s)).ToPointer();
std::string os = chars;

System::Runtime::InteropServices::Marshal::FreeHGlobal(
System::IntPtr((void*)chars));

return
os;
}

Pattern the second, wrapping managed objects
The two classes below provide a simple means to wrap an unmanaged entity within a managed entity. The templated constructor allows you to pass an unmanaged entity to wrap up and whether the managed wrapper is responsible for freeing the memory of the unmanaged entity upon being garbage collected.

/**
adds some useful utility methods to classes that want to
interop between managed and unmanaged code
*/

public ref class
EntityBase {
public private
:
static
std::string MarshalString ( System::String^ s)
{


const
char* chars =
(
const char*)(System::Runtime::InteropServices::
Marshal::StringToHGlobalAnsi(s)).ToPointer();

std::string os = chars;
System::Runtime::InteropServices::Marshal::
FreeHGlobal(System::IntPtr((void*)chars));

return
os;
}
};


/**
provides a means to wrap an unmanaged type inside a managed
entity
*/

template
<typename T> public ref class ManagedEntityBase:
EntityBase
{

public
:
virtual
~ManagedEntityBase()
{

if
(_ownsNativeEntity) {
delete
_nativeEntity;
}
}

public private
://equivalent to internal in c#

property
T *NativeEntity {
T *get()
{

return
_nativeEntity;
}
}


ManagedEntityBase(T *nativeEntity,bool ownsNativeEntity) {
_nativeEntity = nativeEntity;
_ownsNativeEntity = ownsNativeEntity;
}

private
:

T *_nativeEntity;
bool
_ownsNativeEntity;
};
below is an example of how to use these classes

class UnmanagedClass {
public
:
UnmanagedClass(){}
virtual
~UnmanagedClass(){}

int
Foo() {return 1;}
};


public ref class
ManagedClass:
ManagedEntityBase<UnmanagedClass> {
public
:
ManagedClass():
ManagedEntityBase(new UnmanagedClass(),true) {}
virtual
~ManagedClass(){}

int
Foo() { return NativeEntity->Foo(); }
};


Then after referencing the above c++/cli assembly we can access the managed wrapper in c# with the following

ManagedClass mc = new ManagedClass();
int
bar = mc.Foo();

As for mapping boost::signal callbacks to .NET events and delegates, that was a little more tricky and will be the topic of another days post :)

Hasta Luevo.
3 Comments