C++ callback with function pointers - c++

I'm writing a C++ application that uses a 3rd party library to open proprietary files. In my application users can do something like this:
int main(int argc, char* argv[]) {
CustomFileFormat f1;
f1.open( "c:/file1.xyz" );
f1.process();
CustomFileFormat f2;
f2.open( "c:/file2.xyz" );
f2.process();
Result r = f1.compare( f2 );
r.generateReport();
return 0;
}
The problem that I'm having is with the process() function. This function sends a command to the 3rd party library that exposes a callback function defined like this:
typedef void (*FileProgressCallback)( double dProgress, bool& shouldAbort );
This callback function will be called from the 3rd party library telling me how much of the file has been processed (the received dProgress value will be between 0 and 1) and the shouldAbort bool variable I can use to cause the processing to stop.
The problem that I'm having is I don't know how to code the process() function so that when the callback is called, I know whether the results coming back are for instance f1 or instance f2. Is it possible to define a member function of my CustomFileFormat class, so that when it is called, I know which (this) is being used?

A simple method would be to have a global you set with some context before the .process() call. If you make the global a stack you can even perform recursive processing (although as described it does not sound like that is part of what you need).
A more complex answer would be to use something like libffi's closures (the library is available from https://sourceware.org/libffi/ or https://github.com/libffi/libffi). That part of the library actually generates (small) bits of code at run-time that can associate additional parameters with those received from a caller.

Related

Calling function in an unknown class for libraries

I have a few Libraries defined in C++ source code. My problem is whenever a library is removed or a new one is added, something has to call the libraries "Initialize" function.
An example would be: A class for Network sockets called CLuaNet which has a function called CLuaNet::Initialize(*State);. How do I call this function in my project since I cannot predict the library name? If possible I would like this "linking" to be done at compile time, something like a macro.
Whenever a new instance of a Lua environment is opened, every library's initialize function has to be called with an the Lua state as argument.
The project runs on different architectures (X86/X64/ARMv6/ARMv7) and operating systems, making compiled libraries for every possible platform and OS combination is not feasible (Windows - DLL, Linux - SO, etc..). This is intended to be a server application.
EDIT: I am not using DLLs or SOs - everything is compiled into one executable for portability.
Note: I dont have alot of experience in project design/managment. Id
like to hear opinions and tips about my approach on this.
The normal mechanism for coping with name finding, is to create another well named function which returns sufficient meta data to allow you to call it.
extern "C" DLLEXPORT const MetaInfo & InfoFunction()
{
static MetaInfo luaNet(
CLuaNet::Initialize,
CLuaNet::Finalize,
CLuaNet::SomethingElse );
return luaNet; // Give main application information on how to call me
}
Where DLLEXPORT declares a function to be exported from the DLL/shared object.
MetaInfo is compiled into the DLL/shared object and has a set of well-defined slots which perform useful functions.
e.g.
struct MetaInfo {
int (*initializeFunction)( lua_State * L );
int (*closeFunction)( lua_State * L );
int (*utilityFunction)( lua_State* L );
MetaInfo( int (*)(lua_State *) init,
int (*)( lua_State*) fini,
int (*)( lua_State*) other ) :
initializeFunction( init),
closeFunction( fini ),
utilityFunction( other ) {}
};

Running Function Inside Stub. Passing Function Pointer

I'm working on creating a user-level thread library and what I want to do is run a function inside a stub and so I would like to pass the function pointer to the stub function.
Here is my stub function:
void _ut_function_stub(void (*f)(void), int id)
{
(*f)();
DeleteThread(id);
}
This is what the user calls. What I want to do is get pointer of _ut_function_stub to assign to pc and I've tried various different options including casting but the compiler keeps saying "invalid use of void expression".
int CreateThread (void (*f) (void), int weight)
{
... more code
pc = (address_t)(_ut_function_stub(f, tcb->id));
... more code
}
Any help is appreciated. Thanks!
If you're interested in implementing your own user-level-threads library, I'd suggest looking into the (now deprecated) ucontext implementation. Specifically, looking at the definitions for the structs used in ucontext.h will help you see all the stuff you actually need to capture to get a valid snapshot of the thread state.
What you're really trying to capture with the erroneous (address_t) cast in your example is the current continuation. Unfortunately, C doesn't support first-class continuations, so you're going to be stuck doing something much more low-level, like swapping stacks and dumping registers (hence why I pointed you to ucontext as a reference—it's going to be kind of complicated if you really want to get this right).

How to call a function defined in my exe inside my DLL?

I have some general purpose functions defines in my exe file like Log(char* str). This function takes a string as an input from the caller and writes it to the logfile defined for that application. Now I want to write DLL code which will include a function to upload a file to a server.
The objective is to import the upload function from the DLL into the exe and use it. However, if any error is encountered, then the upload function must call the Log(char* str) function to write the error into the log file.
The trouble is that this DLL needs to be used in multiple applications and each app will have a different logfile at a different location. I want to write the DLL in such a way that it calls the corresponding Log(char* str) defined in the application. Similarly I have some other functions that are application-specific and cannot be included in the DLL beforehand.
How can I write such DLL code where it only knows the function prototype, but not the function definition, which resides inside the exe?
Have a function in your DLL that the .exe can call, passing in a function pointer to your Log function. Inside the DLL, store that function pointer and use it when you need to log things.
If there is more than one such function you need to pass to your DLL, consider using a struct to store all the relevant function pointers.
Here's a good tutorial on function pointers: The function pointer tutorial
To keep this interface simple, I would highly recommend keeping all these "customizable" functions in plain C, at least as a starting point. Dealing with pointer-to-member functions and passing C++ objects around through C wrappers is error-prone. (But doable.) Or stick with C++ all round.
Here's a short example. In a common header, put something like this:
typedef void (*logfunc)(char const*);
to simplify passing around the customized function pointer.
In your DLL code, you could then have:
logfunc cust_log;
void dll_init_logging(logfunc l)
{
cust_log = l;
}
void dll_do_something()
{
cust_log("hello");
}
Modify that to make these functions exportable if necessary on your platform.
Then from your main code, all you need to do (assuming you're loading the DLL and making the exported functions available to your .exe with their original name) is:
void logit(char const* str)
{
printf("Log: %s\n", str);
}
int main (int argc, char const *argv[])
{
// load the DLL
dll_init_logging(logit);
...
dll_do_something();
...
return 0;
}

C++ DLL which can inform a calling program about its progress

My boss wants me to write a DLL in C++ (MSVC++2010) which can perform a Volume Shadow Copy which he can call from VB6 (or at a later point other languages) and which can give status updates back while it is not finished. He calls it "events".
I have the feeling that I finally need to learn COM (I'd rather not ...) ... also, a callback function comes to my mind, but it's surely impossible to hand over function pointers from VB6 to C++?
Can someone outline what I have to learn and how this can be accomplished, with or without COM?
EDIT:
to answer a question, the work flow is supposed to be:
VB6 app determines which files to back up
I am given a path and make a temporary volume shadow copy which includes this path and give back a mount point (or similar)
during this step, I regularly tell the VB6 app how far I am
VB6 app makes backup of shadow copy and then deletes shadow copy.
You can pass a pointer to your "display progress" function from the VB app to the C++ DLL app using the AddressOf operator:
Declare Function CallMyDll ...
Sub DisplayStatus(ByVal SomeParameter As Long)
' ...
End SUb
Sub DoSomething()
Call CallMyDll(AddressOf DisplayStatus)
End Sub
Some not so obvious gotchas:
You have to declare your C++ function pointer using the __stdcall calling convention. (Thanks, Alexandre C!)
In your VB callback function, explicitly mark your parameters as by-value using the keyword ByVal. Similarly, in your C++ function pointer, don't mark your parameters as by-reference.
If you want to pass a string to the callback, or retrieve a string from it, you have to take into consideration that VB Strings are not equal to C char*s, C++ std::strings, or Microsoft's CStrings. VB Strings must be mapped to Microsoft's rather obscure BSTR data type.
I forgot a very important thing: Your callback has to be inside a VB Module (i.e., it has to be a "mere function", not a class' or a form's method).
Your boss can call functions exported by a DLL with the Declare statement. That doesn't scale well but is fine for a simple API. Your function should be exported with the extern "C" and __declspec(dllexport) declarators, use the __stdcall calling convention and use only simple argument types.
When it has to provide these status updates?
While setting up VSS? Or while backing up the data and such?
In the latter case VSS just returns a path, which can be used
directly from VB.
But for setup... it might make sense too, because it can be fairly slow,
but I guess you can turn it into a state machine - put all the VSS API calls
into a big switch() and make a function which would call them one by one and
update the state var.
Update: I mean something like this.
Init() and Step() are your functions exported by your dll and called from VB.
Alternatively, you can spawn a thread to do all that (still in the dll) and return
status updates after like Sleep(100) in Step().
int s; // state
int Init( void ) { s=0; }
int Step( void ) {
switch( s ) {
default: break;
case 0:
CoInitialize(0); break;
case 1:
r = CreateVssBackupComponents(&vssc);
if( FAILED(r) ) s=-1;
if( vssc==0 ) s=-2;
break;
case 2:
r = vssc->InitializeForBackup();
if( FAILED(r) ) s=-3;
break;
case 3:
r = vssc->SetBackupState( FALSE, FALSE, VSS_BT_COPY, FALSE );
if( FAILED(r) ) s=-4;
break;
[...]
}
s += (s>=0);
}
I would do the job without COM. Instead, I'd have the VB part send a window handle to the DLL, and the DLL will post a message to the window telling its progress.
You could use COM, but that's kind of in the range of swatting a fly with a sledgehammer.
Take the unix-y route. Create a PROGRAM that performs the copy and outputs a progress indicator to std out. Make the VB app parse this output to grab the completion percentage.
I would do this:
the VB app calls the function in your DLL asking to start the shadow copy. Your Dll starts a thread that performs the shadow copy and returns an ID (a thread id?) back to the VB app
The VB app calls periodically a function "Progress" in your DLL passing the operation ID received before: the progress function returns an integer 0-100 to indicate the progress
This way the VB app can launch several operations in parallel.
The thread that performs the copy should update a "progress" variable every now and then.
Another function in the DLL that stops the copy would be useful too.

Compiling a DLL with gcc

Sooooo I'm writing a script interpreter. And basically, I want some classes and functions stored in a DLL, but I want the DLL to look for functions within the programs that are linking to it, like,
program dll
----------------------------------------------------
send code to dll-----> parse code
|
v
code contains a function,
that isn't contained in the DLL
|
list of functions in <------/
program
|
v
corresponding function,
user-defined in the
program--process the
passed argument here
|
\--------------> return value sent back
to the parsing function
I was wondering basically, how do I compile a DLL with gcc? Well, I'm using a windows port of gcc. Once I compile a .dll containing my classes and functions, how do I link to it with my program? How do I use the classes and functions in the DLL? Can the DLL call functions from the program linking to it? If I make a class { ... } object; in the DLL, then when the DLL is loaded by the program, will object be available to the program? Thanks in advance, I really need to know how to work with DLLs in C++ before I can continue with this project.
"Can you add more detail as to why you want the DLL to call functions in the main program?"
I thought the diagram sort of explained it... the program using the DLL passes a piece of code to the DLL, which parses the code, and if function calls are found in said code then corresponding functions within the DLL are called... for example, if I passed "a = sqrt(100)" then the DLL parser function would find the function call to sqrt(), and within the DLL would be a corresponding sqrt() function which would calculate the square root of the argument passed to it, and then it would take the return value from that function and put it into variable a... just like any other program, but if a corresponding handler for the sqrt() function isn't found within the DLL (there would be a list of natively supported functions) then it would call a similar function which would reside within the program using the DLL to see if there are any user-defined functions by that name.
So, say you loaded the DLL into the program giving your program the ability to interpret scripts of this particular language, the program could call the DLLs to process single lines of code or hand it filenames of scripts to process... but if you want to add a command into the script which suits the purpose of your program, you could say set a boolean value in the DLL telling it that you are adding functions to its language and then create a function in your code which would list the functions you are adding (the DLL would call it with the name of the function it wants, if that function is a user-defined one contained within your code, the function would call the corresponding function with the argument passed to it by the DLL, the return the return value of the user-defined function back to the DLL, and if it didn't exist, it would return an error code or NULL or something). I'm starting to see that I'll have to find another way around this to make the function calls go one way only
This link explains how to do it in a basic way.
In a big picture view, when you make a dll, you are making a library which is loaded at runtime. It contains a number of symbols which are exported. These symbols are typically references to methods or functions, plus compiler/linker goo.
When you normally build a static library, there is a minimum of goo and the linker pulls in the code it needs and repackages it for you in your executable.
In a dll, you actually get two end products (three really- just wait): a dll and a stub library. The stub is a static library that looks exactly like your regular static library, except that instead of executing your code, each stub is typically a jump instruction to a common routine. The common routine loads your dll, gets the address of the routine that you want to call, then patches up the original jump instruction to go there so when you call it again, you end up in your dll.
The third end product is usually a header file that tells you all about the data types in your library.
So your steps are: create your headers and code, build a dll, build a stub library from the headers/code/some list of exported functions. End code will link to the stub library which will load up the dll and fix up the jump table.
Compiler/linker goo includes things like making sure the runtime libraries are where they're needed, making sure that static constructors are executed, making sure that static destructors are registered for later execution, etc, etc, etc.
Now as to your main problem: how do I write extensible code in a dll? There are a number of possible ways - a typical way is to define a pure abstract class (aka interface) that defines a behavior and either pass that in to a processing routine or to create a routine for registering interfaces to do work, then the processing routine asks the registrar for an object to handle a piece of work for it.
On the detail of what you plan to solve, perhaps you should look at an extendible parser like lua instead of building your own.
To your more specific focus.
A DLL is (typically?) meant to be complete in and of itself, or explicitly know what other libraries to use to complete itself.
What I mean by that is, you cannot have a method implicitly provided by the calling application to complete the DLLs functionality.
You could however make part of your API the provision of methods from a calling app, thus making the DLL fully contained and the passing of knowledge explicit.
How do I use the classes and functions in the DLL?
Include the headers in your code, when the module (exe or another dll) is linked the dlls are checked for completness.
Can the DLL call functions from the program linking to it?
Yes, but it has to be told about them at run time.
If I make a class { ... } object; in the DLL, then when the DLL is loaded by the program, will object be available to the program?
Yes it will be available, however there are some restrictions you need to be aware about. Such as in the area of memory management it is important to either:
Link all modules sharing memory with the same memory management dll (typically c runtime)
Ensure that the memory is allocated and dealloccated only in the same module.
allocate on the stack
Examples!
Here is a basic idea of passing functions to the dll, however in your case may not be most helpfull as you need to know up front what other functions you want provided.
// parser.h
struct functions {
void *fred (int );
};
parse( string, functions );
// program.cpp
parse( "a = sqrt(); fred(a);", functions );
What you need is a way of registering functions(and their details with the dll.)
The bigger problem here is the details bit. But skipping over that you might do something like wxWidgets does with class registration. When method_fred is contructed by your app it will call the constructor and register with the dll through usage off methodInfo. Parser can lookup methodInfo for methods available.
// parser.h
class method_base { };
class methodInfo {
static void register(factory);
static map<string,factory> m_methods;
}
// program.cpp
class method_fred : public method_base {
static method* factory(string args);
static methodInfo _methoinfo;
}
methodInfo method_fred::_methoinfo("fred",method_fred::factory);
This sounds like a job for data structures.
Create a struct containing your keywords and the function associated with each one.
struct keyword {
const char *keyword;
int (*f)(int arg);
};
struct keyword keywords[max_keywords] = {
"db_connect", &db_connect,
}
Then write a function in your DLL that you pass the address of this array to:
plugin_register(keywords);
Then inside the DLL it can do:
keywords[0].f = &plugin_db_connect;
With this method, the code to handle script keywords remains in the main program while the DLL manipulates the data structures to get its own functions called.
Taking it to C++, make the struct a class instead that contains a std::vector or std::map or whatever of keywords and some functions to manipulate them.
Winrawr, before you go on, read this first:
Any improvements on the GCC/Windows DLLs/C++ STL front?
Basically, you may run into problems when passing STL strings around your DLLs, and you may also have trouble with exceptions flying across DLL boundaries, although it's not something I have experienced (yet).
You could always load the dll at runtime with load library