I'm trying to detour a function in an application. I have it's source available.
class Foot : public Something, public SomethingElse {
public:
Foot( double SomethingAgain, double Somethings,
Blahblah *AnotherThing = NULL );
virtual ~Foot();
virtual void detourmepls( const char *ARGUMENT );
};
This is how it was defined in the header file.
This is what I used to define it so I would call it from my dll using the correct address.
void (__cdecl* detourmepls)(const char *stuff);
What's the true calling convention for this virtual void function?
Any help is appreciated.
NEW EDITS AND INFOS:
I'm using MS Detours 1.5
detourmepls = (void(__thiscall*)(void *Pthis,void *Unknown,const char *))DetourFunction((PBYTE)ADDRESS, (PBYTE)hookedFunction);
This is how I tried the detour ( its pretty messed up. )
Background
Callbacks with virtual functions require a 'this' object to resolve the virtual function. A virtual function pointer is actually more like a vtable "offset" (and quite hairy in the presence of multiple virtual double-secret inheritance ;).
__cdecl doesn't support any of that.
What does the API were you register your callback look like? It sound's like a C-api. These sometimes take a void*. If not, then you need to store the object somehwere else.
Callback is function only, no data
If it's only a callback function, and no user data, you need to store the object pointer seprately on your side and resolve the virtual function call in a static function, which is the one you register.
void registerCallback(void (__cdecl* callbackfn)(const char* stuff));
class Foo {
static Foo* s_callback_object;
~Foo() {
// never hurts
if (this == s_callback_object)
s_callback_object = 0;
}
static void Foo::callbackResolver(const char* stuff) {
assert(s_callback_object);
s_callback_object->detourmepls(stuff);
}
}
Fop* foo::s_callback_object = 0;
Foo myFoo;
Foo::s_callback_object = &myFoo;
registerCallback(&Foo::callBackResolver);
Callback function with user data arg:
(This is how it should be done, folks)
For case 2, user data, you can cast that to your object instead:
void registerCallback(void (__cdecl* callbackfn)(const char* stuff),
void *userdata);
class Foo {
static void Foo::callbackResolver(const char* stuff, void *userdata) {
Foo* foo = reinterpret_cast<Foo*>(userdata);
foo->detourmepls(stuff);
}
}
Foo myFoo;
registerCallBack(&Foo::callbackResolver, &myFoo);
The latter scheme is immensely useful even in plain C programming, so if you do your own API's, do it like this. :)
Related
Given the following C interface:
IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient,
const char *pTopicName,
uint16_t topicNameLen,
QoS qos,
pApplicationHandler_t pApplicationHandler,
oid *pApplicationHandlerData);
"aws_iot_mqtt_subscribe stores its arguments for latter reference - to call, in response to some event at some later point in time"
Handler:
typedef void (*pApplicationHandler_t)(
AWS_IoT_Client *pClient,
char *pTopicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *pParams,
void *pClientData);
I am trying to wrap this into a C++ class that would have the following interface:
class AWS {
// ...
public:
void subscribe(const std::string &topic,
std::function<void(const std::string&)> callback);
// ...
};
My goal is to make it possible to pass a capturing lambda function to AWS::subscribe. I have been trying with different approaches for a nearly a week now but none of them seemed to work.
Let me know if anything else needed to understand the problem, I'm happy to update the question.
The basic approach is to store a copy of callback somewhere, then pass a pointer to it as your pApplicationHandlerData.
Like this:
extern "C"
void application_handler_forwarder(
AWS_IoT_Client *pClient,
char *pTopicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *pParams,
void *pClientData
) {
auto callback_ptr = static_cast<std::function<void(const std::string&)> *>(pClientData);
std::string topic(pTopicName, topicNameLen);
(*callback_ptr)(topic);
}
This is your (C compatible) generic handler function that just forwards to a std::function referenced by pClientData.
You'd register it in subscribe as
void AWS::subscribe(const std::string &topic, std::function<void(const std::string&)> callback) {
...
aws_iot_mqtt_subscribe(pClient, topic.data(), topic.size(), qos,
application_handler_forwarder, ©_of_callback);
where copy_of_callback is a std::function<const std::string &)>.
The only tricky part is managing the lifetime of the callback object. You must do it manually in the C++ part because it needs to stay alive for as long as the subscription is valid, because application_handler_forwarder will be called with its address.
You can't just pass a pointer to the parameter (&callback) because the parameter is a local variable that is destroyed when the function returns. I don't know your C library, so I can't tell you when it is safe to delete the copy of the callback.
N.B: Apparently you need extern "C" on the callback even if its name is never seen by C code because it doesn't just affect name mangling, it also ensures the code uses the calling convention expected by C.
Why it does not work just like that
The reason you can not just pass a C++ function into a C API is because the two have potentially different calling conventions. The extern "C" syntax is to tell the C++ compiler to use the C notation for a single function or for the whole code block if used like extern "C" { ... }.
How to make it work
Create a singleton C++ wrapper around the C API responsible for the initialization/finalization of the latter and forwarding calls and callbacks back and forth. Importantly it should try minimising the amount of raw C++ world pointers into the C API to make clean memory management possible.
godbolt // apologies for the clumsy syntax, too much Java recently :-)
extern "C" {
void c_api_init();
void c_api_fini();
void c_api_subscribe(
char const* topic,
void(*cb)(void*),
void* arg);
}
// this is the key of the trick -- a C proxy
extern "C" void callback_fn(void* arg);
using callaback_t = std::function<void(std::string const&)>;
struct ApiWrapper {
// this should know how to get the singleton instance
static std::unique_ptr<ApiWrapper> s_singleton;
static ApiWrapper& instance() { return *s_singleton; }
// ctor - initializes the C API
ApiWrapper(...) { c_api_init(); }
// dtor - shuts down the C API
~ApiWrapper() { c_api_fini(); }
// this is to unwrap and implement the callback
void callback(void* arg) {
auto const sub_id = reinterpret_cast<sub_id_t>(arg);
auto itr = subs_.find(sub_id);
if (itr != subs_.end()) {
itr->second(); // call the actual callback
}
else {
std::clog << "callback for non-existing subscription " << sub_id;
}
}
// and this is how to subscribe
void subscribe(std::string const& topic, callaback_t cb) {
auto const sub_id = ++last_sub_id_;
subs_[sub_id] = [cb = std::move(cb), topic] { cb(topic); };
c_api_subscribe(topic.c_str(), &callback_fn, reinterpret_cast<void*>(sub_id));
}
private:
using sub_id_t = uintptr_t;
std::map<sub_id_t, std::function<void()>> subs_;
sub_id_t last_sub_id_ = 0;
};
Create a C-proxy to bridge between the C API and the C++ wrapper
// this is the key of the trick -- a C proxy
extern "C" void callback_fn(void* arg) {
ApiWrapper::instance().callback(arg);
}
I need to use an unmanaged API from C++/CLI. This API stores a void pointer to arbitrary user data and a few callbacks. It then eventually calls those callbacks, passing the user data in as void*.
So far I had a native class passing its "this" pointer as the user data, and using that pointer to have the API call back into this class, i.e.:
static void __stdcall Callback(void* userData) {
((MyType*)userData)->Method();
}
class MyType {
public:
MyType() { RegisterWithApi((void*)this, Callback); }
void Method();
};
I'm trying to translate this using a managed class. I found that the type gcroot can be used to safely store a managed reference in native code, so here's how I'm doing it now:
// This is called by the native API
static void __stdcall Callback(void* userData) {
// Cast back to gcroot and call into managed code
(*(gcroot<MyType^>*)userData)->Method();
}
ref class MyType {
gcroot<MyType^>* m_self;
public:
MyType() {
m_self = new gcroot<MyType^>;
RegisterWithApi((void*)m_self, Callback);
}
~MyType() { delete m_self; }
// Method we want called by the native API
void Method();
}
While this seems fine to the C++/CLI compiler, I am not perfectly re-assured. From what I understand, gcroot somehow keeps track of its managed reference as it is moved by the GC. Will it manage to do this while stored as a void* by unmanaged code? Is this code safe?
Thanks.
This is what I ended up doing and it works perfectly. The purpose of gcroot is to store a managed reference on the native heap, which is precisely what I'm doing here.
No! It's exactly the other way around. gcroot is a native class template. You use it to store a handle to managed memory in a native type which is compiled with clr support. You will typically use it to divert calls to member functions of a native object to a managed object stored in a member of type gcroot.
EDIT: I was on mobile yesterday where typing code examples is a bit awkward... The intended and typical usage of gcroot<T^> is somewhere along these lines:
// ICallback.h
struct ICallback {
virtual void Invoke() = 0;
virtual void Release() = 0;
protected:
~ICallback() {}
};
That is what your native apps or libraries see and include. Then, you have a mixed component compiled with CLR support, which implements ICallback and stores a handle to some managed object in a gcroot<ManagedType^>:
// Callback.cpp (this translation unit must be compiled with /clr)
// I did not compile and test, but you get the point...
template<class T^> class Callback : public ICallback {
gcroot<T^> m_Managed;
virtual void Invoke()
{
m_Managed->Invoke();
}
virtual void Release()
{
delete this;
}
public:
Callback(T^ p_Managed) : m_Managed(p_Managed) {}
};
__declspec( dllexport ) ICallback* CreateCallback()
{
auto t_Managed = gcnew SomeManagedType();
return new Callback<System::Action^>(
gcnew System::Action(t_Managed, &SomeManagedType::Method));
}
Your native apps call CreateCallback, recieve an instance of ICallback which when Invoke-d calls a method of managed type, held in gcroot<System::Action^>...
I'm using an API that requires me to pass a function pointer as a callback. I'm trying to use this API from my class in C++ but I'm getting compilation errors.
The API definition is:
typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);
__declspec(dllimport) int __stdcall set_stream_callback(
STREAM_CALLBACK streamCB, void *userdata);
One example file, provided by the third party, is:
void __stdcall streamCB(void *userdata)
{
// callback implementation
}
int main(int argc, const char argv[])
{
int mid = 0;
set_stream_callback(streamCB, &mid);
}
And that works fine.
However when I try to use that in a class, I have an error:
error C3867: 'MyClass::streamCB': function call missing argument list;
use '&MyClass::streamCB' to create a pointer to member
The suggestion to use
&MyClass::streamCB
doesn't work.
I understood that the set_stream_callback only accepts a non-member function.
The problem is very similar to
How can I pass a class member function as a callback?
in which Johannes makes a concise suggestion, however I do not understand it very well. Could anyone expand a bit, if I am correct that it is relevant to this question?
I have tried:
void __stdcall MyClass::streamCB(void *userdata)
{
// callback implementation
}
static void MyClass::Callback( void * other_arg, void * this_pointer ) {
MyClass * self = static_cast<ri::IsiDevice*>(this_pointer);
self->streamCB( other_arg );
}
//and in the constructor
int mid = 0;
set_stream_callback(&MyClass::Callback, &mid);
But
error C2664: 'set_stream_callback' : cannot convert parameter 1 from
'void (__cdecl *)(void *,void *)' to 'STREAM_CALLBACK'
How do I get around this?
Edit1: Also, I want to use userdata inside the streamCB callback.
The idea of calling a member function from a callback taking only non-member functions is to create a wrapper for you member function. The wrapper obtains an object from somewhere and then calls the member function. If the callback is reasonably well designed it will allow you to pass in some "user data" which you'd use to identify your object. You, unfortunately, left out any details about your class so I'm assuming it looks something like this:
class MyClass {
public:
void streamCB() {
// whatever
}
// other members, constructors, private data, etc.
};
With this, you can set up your callback like so:
void streamCBWrapper(void* userData) {
static_cast<MyClass*>(userData)->streamCB()
}
int main() {
MyClass object;
set_stream_callback(&streamCBWrapper, &object);
// ...
}
There are various games you can play with how to create the streamCBWrapper function (e.g., you can make it a static member of your class) but all come down to the same: you need to restore your object from the user data and call the member function on this object.
You can achieve what you want to do by turning the userdata into a property of MyClass. Then you don't have to pass it to MyClass::Callback, which would be impossible, since you can only pass one parameter, and it would be the object instance.
Here's an example.
void __stdcall MyClass::streamCB()
{
// callback implementation
}
static void MyClass::Callback(void * this_pointer ) {
MyClass * self = static_cast<MyClass>(this_pointer);
self->streamCB();
}
MyClass::MyClass(void *userdata) {
// do whatever you need to do with userdata
// (...)
// and setup the callback at C level
set_stream_callback(&MyClass::Callback, (void *)this);
}
In your example, the int mid variable would become a property of that class, and thus be accessible from the callback implementation streamCB.
I'm toying around with the LLVM C++ API. I'd like to JIT compile code and run it.
However, I need to call a C++ method from said JIT-compiled code. Normally, LLVM treats method calls as function calls with the object pointer passed as the first argument, so calling shouldn't be a problem. The real problem is to get that function into LLVM.
As far as I can see, it's possible to use external linkage for functions and get it by its name. Problem is, since it's a C++ method, its name is going to be mangled, so I don't think it's a good idea to go that way.
Making the FunctionType object is easy enough. But from there, how can I inform LLVM of my method and get a Function object for it?
The dudes from the LLVM mailing list were helpful enough to provide a better solution. They didn't say how to get the pointer from the method to the function, but I've already figured out this part so it's okay.
EDIT A clean way to do this is simply to wrap your method into a function:
int Foo_Bar(Foo* foo)
{
return foo->bar();
}
Then use Foo_Bar's address instead of trying to get Foo::bar's. Use llvm::ExecutionEngine::addGlobalMapping to add the mapping as shown below.
As usual, the simplest solution has some interesting benefits. For instance, it works with virtual functions without a hiccup. (But it's so much less entertaining. The rest of the answer is kept for historical purposes, mainly because I had a lot of fun poking at the internals of my C++ runtime. Also note that it's non-portable.)
You'll need something along these lines to figure the address of a method (be warned, that's a dirty hack that probably will only be compatible with the Itanium ABI):
template<typename T>
const void* void_cast(const T& object)
{
union Retyper
{
const T object;
void* pointer;
Retyper(T obj) : object(obj) { }
};
return Retyper(object).pointer;
}
template<typename T, typename M>
const void* getMethodPointer(const T* object, M method) // will work for virtual methods
{
union MethodEntry
{
intptr_t offset;
void* function;
};
const MethodEntry* entry = static_cast<const MethodEntry*>(void_cast(&method));
if (entry->offset % sizeof(intptr_t) == 0) // looks like that's how the runtime guesses virtual from static
return getMethodPointer(method);
const void* const* const vtable = *reinterpret_cast<const void* const* const* const>(object);
return vtable[(entry->offset - 1) / sizeof(void*)];
}
template<typename M>
const void* getMethodPointer(M method) // will only work with non-virtual methods
{
union MethodEntry
{
intptr_t offset;
void* function;
};
return static_cast<const MethodEntry*>(void_cast(&method))->function;
}
Then use llvm::ExecutionEngine::addGlobalMapping to map a function to the address you've gotten. To call it, pass it your object as the first parameter, and the rest as usual. Here's a quick example.
class Foo
{
void Bar();
virtual void Baz();
};
class FooFoo : public Foo
{
virtual void Baz();
};
Foo* foo = new FooFoo;
const void* barMethodPointer = getMethodPointer(&Foo::Bar);
const void* bazMethodPointer = getMethodPointer(foo, &Foo::Baz); // will get FooFoo::Baz
llvm::ExecutionEngine* engine = llvm::EngineBuilder(module).Create();
llvm::Function* bar = llvm::Function::Create(/* function type */, Function::ExternalLinkage, "foo", module);
llvm::Function* baz = llvm::Function::Create(/* function type */, Function::ExternalLinkage, "baz", module);
engine->addGlobalMapping(bar, const_cast<void*>(barMethodPointer)); // LLVM always takes non-const pointers
engine->addGlobalMapping(baz, const_cast<void*>(bazMethodPointer));
One way is a C wrapper around the desired method, i.e.
extern "C" {
void wrapped_foo(bar *b, int arg1, int arg2) {
b->foo(arg1, arg2);
}
}
The extern "C" bit makes the function use C calling conventions and prevents any name mangling. See http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6 for details on C/C++ interop including extern "C"
You should also probably be able to get the address of the function in your C++ code and then store that address in a global known to LLVM.
Huh, using the non-standard dladdr and a ridiculously convoluted and unsafe way to cast method pointers to void pointers, there seems to be a way to obtain the name of a method from its pointer.
This is certainly more dangerous than firearms. Don't do this at home (or at work, for that matter).
C++ forbids to cast method pointers to void* (which is required by dladdr to work) even with the almighty C cast, but you can cheat that.
#include <string>
#include <dlfcn.h>
template<typename T>
static void* voidify(T method)
{
asm ("movq %rdi, %rax"); // should work on x86_64 ABI compliant platforms
}
template<typename T>
const char* getMethodName(T method)
{
Dl_info info;
if (dladdr(voidify(method), &info))
return info.dli_sname;
return "";
}
From there:
int main()
{
std::cout << getMethodName(&Foo::bar) << std::endl;
// prints something like "_ZN3Foo3barEv"
}
...aaaand you should be able to use that symbol name with LLVM. But it won't work with virtual methods (another good reason to not use it).
EDIT Hacking much, much deeper into how virtual method pointers are handled, I've put together a more elaborate function that works for them, too. Only the most courageous of you should follow this link.
I've tried all sorts of design approaches to solve this problem, but I just can't seem to get it right.
I need to expose some static functions to use as callback function to a C lib. However, I want the actual implementation to be non-static, so I can use virtual functions and reuse code in a base class. Such as:
class Callbacks {
static void MyCallBack() { impl->MyCallBackImpl(); }
...
class CallbackImplBase {
virtual void MyCallBackImpl() = 0;
However I try to solve this (Singleton, composition by letting Callbacks be contained in the implementor class, etc) I end up in a dead-end (impl usually ends up pointing to the base class, not the derived one).
I wonder if it is at all possible or if I'm stuck with creating some sort of helper functions instead of using inheritance?
Problem 1:
Though it may look and seem to work on your setup this is not guaranteed to work as the C++ ABI is not defined. So technically you can not use C++ static member functions as functions pointers to be used by C code.
Problem 2:
All C callacks (that I know of) allow you to pass user data back as a void*. You can use this as the pointer to your object that has the virtual method. BUT You must make sure you use dynamic_cast<>() to the base class (the one with the virtual method used in the callback) before it is converted into the void* otherwise the pointer at the other end may not be interpreted correctly (especially if there is multiple inheritance involved).
Problem 3:
Exceptions: C is not designed to work with exceptions (especially old C libraries with callbacks). So don't expect exceptions that escape your callback to provide anything meaningful to the caller (they are more likely to result in application termination).
Solution:
What you need to do is use extern "C" function as the callback that calls the virtual method on an object of know type and throws away all exceptions.
An example for the C pthread routines
#include <iostream>
extern "C" void* start_thread(void* data);
class Work
{
public:
virtual ~Work() {}
virtual void doWork() = 0;
};
/*
* To be used as a callback for C code this MUST be declared as
* with extern "C" linkage to make sure the calling code can
* correctly call it
*/
void* start_thread(void* data)
{
/*
* Use reinterpret_cast<>() because the only thing you know
* that you can do is cast back to a Work* pointer.
*
*/
Work* work = reinterpret_cast<Work*>(data);
try
{
work->doWork();
}
catch(...)
{
// Never let an exception escape a callback.
// As you are being called back from C code this would probably result
// in program termination as the C ABI does not know how to cope with
// exceptions and thus would not be able to unwind the call stack.
//
// An exception is if the C code had been built with a C++ compiler
// But if like pthread this is an existing C lib you are unlikely to get
// the results you expect.
}
return NULL;
}
class PrintWork: public Work
{
public:
virtual void doWork()
{
std::cout << "Hi \n";
}
};
int main()
{
pthread_t thread;
PrintWork printer;
/*
* Use dynamic_cast<>() here because you must make sure that
* the underlying routine receives a Work* pointer
*
* As it is working with a void* there is no way for the compiler
* to do this intrinsically so you must do it manually at this end
*/
int check = pthread_create(&thread,NULL,start_thread,dynamic_cast<Work*>(&printer));
if (check == 0)
{
void* result;
pthread_join(thread,&result);
}
}
It's possible. Perhaps there's a problem on how you're initializing the concrete implementation?
In fact, I remember one library that does something very similar to this. You might find it usefull to take a look at libxml++ source code. It's built on top of libxml, which is a C library.
libxml++ uses a struct of static functions to handle the callbacks. For customization, the design allows the user to provide (through virtual functions) his/her own implementations to which the callbacks are then forwarded. I guess this is pretty much your situation.
Something like the below. The singleton is in class Callback, the Instance member will return a statically allocated reference to a CallbackImpl class. This is a singleton because the reference will only be initialised once when the function is first called. Also, it must be a reference or a pointer otherwise the virtual function will not work.
class CallbackImplBase
{
public:
virtual void MyCallBackImpl() = 0;
};
class CallbackImpl : public CallbackImplBase
{
public:
void MyCallBackImpl()
{
std::cout << "MyCallBackImpl" << std::endl;
}
};
class Callback
{
public:
static CallbackImplBase & Instance()
{
static CallbackImpl instance;
return instance;
}
static void MyCallBack()
{
Instance().MyCallBackImpl();
}
};
extern "C" void MyCallBack()
{
Callback::MyCallBack();
}
Are any of the parameters passed to the callback function user defined? Is there any way you can attach a user defined value to data passed to these callbacks? I remember when I implemented a wrapper library for Win32 windows I used SetWindowLong() to attach a this pointer to the window handle which could be later retrieved in the callback function. Basically, you need to pack the this pointer somewhere so that you can retrieve it when the callback gets fired.
struct CALLBACKDATA
{
int field0;
int field1;
int field2;
};
struct MYCALLBACKDATA : public CALLBACKDATA
{
Callback* ptr;
};
registerCallback( Callback::StaticCallbackFunc, &myCallbackData, ... );
void Callback::StaticCallbackFunc( CALLBACKDATA* pData )
{
MYCALLBACKDATA* pMyData = (MYCALLBACKDATA*)pData;
Callback* pCallback = pMyData->ptr;
pCallback->virtualFunctionCall();
}