Using LLVM JIT code to encode a program to call C++ code - c++

My project has a C++ library that I want to allow the user to use via some programming language to be JIT'd to call functions in said library. For the sake of simplicity, assume the library has classes like:
class item {
public:
item();
item( int );
~item();
// ...
};
class item_iterator {
public:
virtual ~item_iterator();
virtual bool next( item *result ) = 0;
};
class singleton_iterator : public item_iterator {
public:
singleton_iterator( item const &i );
// ...
};
I'm aware that LLVM doesn't know anything about C++ and that one way to call C++ functions is to wrap them in C thunks:
extern "C" {
void thunk_item_M_new( item *addr ) {
new( addr ) item;
}
void thunk_singleton_iterator_M_new( singleton_iterator *addr, item *i ) {
new( addr ) singleton_iterator( *i );
}
bool thunk_iterator_M_next( item_iterator *that, item *result ) {
return that->next( result );
}
} // extern "C"
The first problem is how to allocate an item from LLVM. I know how to create StructTypes and add fields to them, but I don't want to have to parallel the C++ class layout -- that's tedious and error-prone.
The idea I got was simply to add a char[sizeof(T)] as the only field to a StructType for a C++ class type:
StructType *const llvm_item_type = StructType::create( llvm_ctx, "item" );
vector<Type*> llvm_struct_types;
llvm_struct_types.push_back( ArrayType::get( IntegerType::get( llvm_ctx, 8 ), sizeof( item ) ) );
llvm_item_type->setBody( llvm_struct_types, false );
PointerType *const llvm_item_ptr_type = PointerType::getUnqual( llvm_item_type );
I would think that, because it's a StructType, the alignment would be correct and the sizeof(item) would get the size right. Will that work? Is there a better way?
The second problem is that, unlike the C++ class hierarchy, there's no inheritance relationship between StructTypes. If I create a Function that takes an llvm_iterator_type but try to build a Function object using an llvm_singleton_iterator_type, the LLVM verifyModule() function complains at me:
Call parameter type does not match function signature!
So then I thought I'd simply use void* everywhere:
Type *const llvm_void_type = Type::getVoidTy( llvm_ctx );
PointerType *const llvm_void_ptr_type = PointerType::getUnqual( llvm_void_type );
but verifyModule() still complains at me because, apparently, there's no automatic casting to void* types in LLVM. How can I solve this problem?

It turns out that using char[sizeof(T)] is a reasonable way to gets StructTypes to be the correct size -- at least one other person from the LLVM mailing list does this.
As for the "Call parameter type does not match function signature!" errors, a solution to that is simply to have all thunks use void* and use static_casts inside. When passing arguments to the thunks, use the CreateBitCast() IRBuilder function (since casts-tovoid are not automatic in LLVM).

Related

How to use custom type function pointer in C++

Condition
I use a framework that has an custom type as bellow:
typedef log (*CustomType) (
int timeStamp,
const char* data,
int dataSize,
void* userData,
int dataType,
int viewId
)
and MyClass init method as bellow:
MyClass_Init (void **output, CustomType video, CustomType audio, void* userData)
Question
I used init method like bellow but always receive error (error content is not displayed because i use a framework). pls point me what is missed.
CustomType videoInput;
CustomType audioInput;
void *output = malloc(sizeof(void*);
void *userData = malloc(sizeof(void*));
long result = MyClass_Init(&output, videoInput, audioInput, userData);
A number of things wrong with this code:
You can't intermix function pointers and method pointers. What it boils down to is that the this for a method has to be included in the method call signature. Since the function pointer doesn't include the this pointer (it is a function, not a method pointer), the two can not match.
Most C-based API includes some sort of reference value (most frameworks call those refCon, context or userData), so what you can do is create an adapter function that calls your method. The userData parameter in your CustomType parameter list looks like it is one of those (consult the docs to be sure).
You can probably provide a userData wherever you set MyClass_Init as your callback now. So, if that function to provide a callback to the library was called set_callback( MyCustomType callback, void* userData ), do something like
MyClass *obj = new MyClass; // Or however you create your object
set_callback( MyClassCallbackAdapterFunction, obj );
with an adapter function like:
log MyClassCallbackAdapterFunction( int timeStamp, const char* data, int dataSize, void* userData, int dataType, int viewId )
{
MyClass *myThis = (MyClass*) userData;
// Here you can now call myThis->MyClass_Init( ... ) however you want to.
}
The malloc( sizeof(void*) ) statements look like you're misunderstanding return parameters (also called "side effects" by some teachers). I don't have the docs to whatever API/library you're using, but I'm pretty certain you're supposed to not just pass in buffers the size of a pointer. Either you'd just provide a pointer on the stack in which a buffer will be returned, or you provide a whole buffer (e.g. an array) and its size, and that is where the callback will write to or so.

use a c lib object orientated

I'm using a lib written in C that allows me to read and write midi-files. Although I found an other lib written in C++ that works for me I'm still struggling with the fact: How could I have used the C lib with objects/classes. The lib has a call that takes the path to the midi file and then some function pointers that get called for specific midi-event-types. So it will look like this (abstract):
int main( int argc, char** args )
{
readMidi( args[ 1 ], onMidiEvent, onSysEvent, onError, ... );
}
I tried to use a pointer to an instance of a class that collects the played notes:
class MidiNoteList;
template < MidiNoteList* VMidi > onError( short errmsg, char* msg ) { ... }
...
int main( int argc, char** args )
{
MidiNoteList* m( new MidiNoteList( ) );
readMidi( args[ 1 ], onMidiEvent< m >, onSysEvent< m >, onError< m >, ... );
}
GCC says that m can't be used as constant expression. I understand that m has to be constant at compile time so I'm sure why I can't make it like that. But how can I solve this "problem" in an other way?
Usually such libraries use an extra void * argument that is passed to the function that takes the function pointers and is passed back to all the callback functions. If you have that, you can use it to pass your object pointer, casting it to void and back:
class MyObject;
void errCallback(void *m, short errcode, char *errmsg) {
static_cast<MyObject *>(m)->error(errcode, errmsg);
}
:
MyObject *m = new MyObject();
callLibrary(..., errCallback, m, ...);
If the library doesn't give you that extra argument, you have a problem -- the only other way to get extra data into the callback function is to use a global variable:
static MyObject *m;
void errCallback(short errcode, char *errmsg) {
m->error(errcode, errmsg);
}
:
m = new MyObject();
callLibrary(..., errCallback, ...);
The problem here being that you need to declare a new callback function (and global var) for each distinct object that you want to have receiving callbacks. If you create many such objects dynamically, that becomes unwieldy to manage.

LuaPlus manipulate table from C++

In this guide functions are created to add a monster to a table and to decrease the health of a monster from the table.
You can easily use the two functons like this from a lua script:
monster = objectMgr:CreateObject("HotMamma",5);
monster:Hurt( 1 ) --decrease health by 1
--or
objectMgr:CreateObject("HotMamma",5);
monster = objectMgr:GetObject(0)
monster:Hurt( 1 )
But how can I call these functions from the C++ side?
I mean the original ones: ObjectMgr::CreateObejct(), ObjectMgr::GetObjectByIndex() and Monster::Hurt()
I spend more than 8 hours on trying to figure this out! But nothing did work. :/
My best try was probably this:
// CreateObject modified to return pMonster and accept normal arguments
MonsterPtr monster = objectMgr.CreateObject(pState, "HotMamma", 5);
monster.Hurt( 1 );
This gives me the following error:
class "std::tr1::shared_ptr" has no member "Hurt"
From looking at the file Monster.hpp:
class Monster
{
// ...
public:
Monster( std::string& name, int health );
void Hurt( int damage );
void Push( LuaPlus::LuaState* pState );
int Index( LuaPlus::LuaState* pState );
int NewIndex( LuaPlus::LuaState* pState );
int Equals( LuaPlus::LuaState* pState );
};
typedef std::shared_ptr<Monster> MonsterPtr;
MonsterPtr is a C++ shared_ptr. So syntactically, you would have to call Monster's members with -> operator like:
// ...
monster->Hurt(1);
Edit: There seems to be some more setting up involved. The method signature:
int ObjectMgr::CreateObject( LuaPlus::LuaState* pState )
only accepts LuaState * as its only argument and it's not overloaded so the call above in your example isn't going to work. What you'll have to do is push the arguments onto the stack prior to the call. The setup and usage should look something like the following:
LuaObject _G = pState->GetGlobals();
LuaObject name, life;
name.AssignString(pState, "HotMamma");
life.AssignInteger(pState, 5);
_G["objectMgr"].Push();
name.Push();
life.Push();
MonsterPtr monster = objectMgr.CreateObject(pState);
monster->Hurt(1);

Inject additional data in a method

I am adding the new module in some large library. All methods here are implemented as static. Let me briefly describe the simplified model:
typedef std::vector<double> TData;
double test ( const TData &arg ) { return arg ( 0 ) * sin ( arg ( 1 ) + ...;}
double ( * p_test ) ( const TData> &arg) = &test;
class A
{
public:
static T f1 (TData &input) {
.... //some computations
B::f2 (p_test);
}
};
Inside f1() some computations are performed and a static method B::f2 is called. The f2 method is implemented by another author and represents some simulation algorithm (example here is simplified).
class B
{
public:
static double f2 (double ( * p_test ) ( const TData &arg ) )
{
//difficult algorithm working p_test many times
double res = p_test(arg);
}
};
The f2 method has a pointer to some weight function (here p_test). But in my case some additional parameters computed in f1 for test() methods are required
double test ( const TData &arg, const TData &arg2, char *arg3.... ) { }
How to inject these parameters into test() (and so to f2) to avoid changing the source code of the f2 methods (that is not trivial), redesign of the library and without dirty hacks :-) ?
The most simple step is to override f2
static double f2 (double ( * p_test ) ( const TData &arg ), const TData &arg2, char *arg3.... )
But what to do later? Consider, that methods are static, so there will be problems with objects.
Updated question
Is it possible to make a pointer to a function dependent on some template parameter or do something like that
if (condition) res = p_test(arg);
else res = p_test2(arg, arg2, arg3);
without dirty hacks
Not gonna happen. If you can't modify the source of a function taking a function pointer, you'll have to use an exception vomit to gain the extra arguments. If you had a C++11 compiler (that does not exist yet) which supports thread_local, it's theoretically possible to do something better, or you could use OS-specific TLS. But as of right now, the only portable solution is an exception vomit.
void f(void(*fp)()) { fp(); }
void mah_func() {
try {
throw;
} catch(my_class* m) {
m->func();
}
}
int main() {
my_class m;
try {
throw &m;
} catch(my_class* p) {
f(mah_func);
}
}
Alternatively, in your scenario, modifying f2 doesn't seem to be impossible, only difficult. However, the difficulty of altering it to take a std::function<double(const TData&)> would be very low- all you'd have to do is change the argument type, thanks to operator overloading. It should be a very simple change for even a complex function, as you're only changing the type of the function parameter, all the call sites will still work, etc. Then you can pass a proper function object made through bind or a lambda or somesuch.
"avoid changing", well that's a bit difficult.
however, you can use a static variable to pass arguments across calls of functions that don't pass the arguments.
remember that if there is more than one thread using those function, you need to either use thread local storage (which is what i recommend for that) or else ensure proper mutual exclusion for use of those variables, where in the case of a single variable shared between all the threads means exclusion all the way down the call chain. but do use thread local storage if threading is a problem. and if no threading problem, well, no problem! :-)

Allow managed code in hosted environment to call back unmanaged code

I have C++ code that hosts a clr in order to make use of Managed.dll, written in c#.
This .net has a method like the following that allows code to register for notification of events:
public void Register(IMyListener listener);
The interface looks something like this
public interface IMyListener
{
void Notify(string details);
}
I'd like to do stuff in the C++ part of the program, triggered by the events in the .net world. I would not even mind creating another managed dll for the sole purpose of making Managed.dll more C++-friendly, if that is necessary.
What are my options here? The only one I am sure I could implement is this:
Write another managed dll that listens for those events, queues them and lets the C++ code access the queue via polling
This would of course change from an 'interrupt' style to a 'polling' style with all its advantages and disadvantages and the need to provide for queuing. Can we do without polling? Could I somehow call managed code and provide it a function pointer into the C++ world as the argument?
Update
Thanks to stijn's answer and comments I hope I moved a bit in the right direction, but I guess the main problem still open is how to pass a fn pointer from unmanaged land into the clr hosted environment.
Say I have an "int fn(int)" type of function pointer that I want to pass to the managed world, here are the relevant parts:
Managed code (C++/CLI)
typedef int (__stdcall *native_fun)( int );
String^ MyListener::Register(native_fun & callback)
{
return "MyListener::Register(native_fun callback) called callback(9): " + callback(9);
}
Unmanaged code
typedef int (__stdcall *native_fun)( int );
extern "C" static int __stdcall NativeFun(int i)
{
wprintf(L"Callback arrived in native fun land: %d\n", i);
return i * 3;
}
void callCLR()
{
// Setup CLR hosting environment
...
// prepare call into CLR
variant_t vtEmpty;
variant_t vtRetValue;
variant_t vtFnPtrArg((native_fun) &NativeFun);
SAFEARRAY *psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
LONG index = 0;
SafeArrayPutElement(psaMethodArgs, &index, &vtFnPtrArg);
...
hr = spType->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
NULL, vtEmpty, psaMethodArgs, &vtRetValue);
if (FAILED(hr))
wprintf(L"Failed to invoke function: 0x%08lx\n", hr);
The spType->InvokeMember_3 call will lead to a 0x80131512 result.
Something seems to be wrong with the way I pass the pointer to NativeFun over to the managed world, or how my functions are defined. When using a String^ param instead of the fn ptr, I can call the CLR function successfully.
You can write a seperate dll in C++/CLI and implement the interface there, and forward the logic to C++. From my experience with mixing managed/unmanaged I can say using an intermediate C++/CLI step is the way to go. No fiddling with DllImport and functions only, but a solid bridge between both worlds. It just takes some getting used to the syntax and marshalling, but once you have that it's practically effortless. If you need to hold C++ objects in the managed class, best way is to use something like clr_scoped_ptr.
Code would look like this:
//header
#using <Managed.dll>
//forward declare some native class
class NativeCppClass;
public ref class MyListener : public IMylIstener
{
public:
MyListener();
//note cli classes automatically implement IDisposable,
//which will call this destructor when disposed,
//so used it as a normal C++ destructor and do cleanup here
~MyListener();
virtual void Notify( String^ details );
private:
clr_scoped_ptr< NativeCppClass > impl;
}
//source
#include "Header.h"
#include <NativeCppClass.h>
//here's how I marshall strings both ways
namespace
{
inline String^ marshal( const std::string& i )
{
return gcnew String( i.data() );
}
inline std::string marshal( String^ i )
{
if( i == nullptr )
return std::string();
char* str2 = (char*) (void*) Marshal::StringToHGlobalAnsi( i );
std::string sRet( str2 );
Marshal::FreeHGlobal( IntPtr( str2 ) );
return sRet;
}
}
MyListener::MyListener() :
impl( new NativeCppClass() )
{
}
MyListener::~MyListener()
{
}
void MyListener::Notify( String^ details )
{
//handle event here
impl->SomeCppFunctionTakingStdString( marshal( details ) );
}
update
Here's a simple solution to call callbacks in C++ from the managed world:
pubic ref class CallbackWrapper
{
public:
typedef int (*native_fun)( int );
CallbackWrapper( native_fun fun ) : fun( fun ) {}
void Call() { fun(); }
CallbackWrapper^ Create( ... ) { return gcnew CallbackWrapper( ... ); }
private:
native_fun fun;
}
you can also wrap this in an Action if you want.
Another way is using GetDelegateForFunctionPointer, for example as in this SO question
If someone still needs a better way for this , you can simply pass c++ function to CLR using intptr_t in variant and long in managed , then use Marshall and delegate to invoke your native function , super easy and works like charm.
if you need a code snippet , let me know.