Passing callback functions to C library throwing Access violation - c++

First and foremost, I'm a C# developer working on a project that was thrust on me and I'm feeling very outside of my comfort zone.
That being said, I'm currently attempting to pass 2 callback functions to a C library. I have the functions defined as free functions in my C++ console application.
When I run the application I'm receiving the following extremely unhelpful error at the point that I attempt to pass the functions to the library.
Exception thrown at 0x0000000000000000 in YourApp.exe: 0xC0000005: Access violation executing location 0x0000000000000000
The callbacks are defined in the header file for the accompanying C source file which I have listed below. Note, I did not write the following header.
header.h
typedef void( __stdcall * Callback1 )( void *, int, unsigned int, int, int, int, int );
typedef void( __stdcall * Callback2 )( void *, int, int, unsigned int, unsigned int );
__declspec(dllimport) int open( Callback1 cb1, Callback2 cb2 );
From my C++ console application I first include the C header.
extern "C"
{
#include "header.h"
}
I then declare the 2 free functions I'm attempting to pass as parameters to the open function exposed through the header.h file.
void __stdcall callback1(
void *data,
int count,
unsigned int colorId,
int flag,
int pageNumber,
int width,
int height )
{
if ( count <= 0 ) return;
std::cout << "callback1" << std::endl;
}
void __stdcall callback2(
void *data,
int count,
int offset,
unsigned int colorId,
unsigned int side )
{
if ( count <= 0 ) return;
std::cout << "callback2" << std::endl;
}
Within main I then attempt to pass the above functions as parameters to the open function.
int main( int argc, char *argv[ ], char *envp[ ] )
{
// This is the line where the error is thrown.
open( callback1, callback2 );
}
I'm currently using VS2015. I'm unsure how to proceed as I find that error extremely unhelpful.
I'm currently doing everything in the code file that main is defined in. So the functions I have posted above are not methods of a class.

Related

Using function declared in C++ dll and its VB declarations

There is a .dll and .lib file for the evaluation board AD5501 after installing its drivers. It contains the functions to use to connect to the board and send instructions to it.
A quick search in analog's website (https://ez.analog.com/thread/11121) revealed a document that contains the commands in the above mentioned DLL file. And it is mentioned that the DLL is written in C++. At the end of the page there is a pdf containing VB6 function declarations of the DLL.
I have no knowledge of VB6 but the fact that the DLL has been written in C++ led me to assume that I should be able to access the function in the DLL or LIB file if i know the function prototype in a C++ program. Is this a correct assumption?
And the website has description of the function prototype. So i made a test C++ program as given below :
#include <iostream>
using namespace std;
unsigned int Search_For_Boards (unsigned int VID, unsigned int PID, unsigned int *Num_boards, char *PartPath[]);
int Connect(unsigned int VID, unsigned int PID, char PartPath, unsigned int *Handle);
int Download_Firmware(unsigned int Handle, char pcFilePath[]);
int Vendor_Request(unsigned int Handle, unsigned char Request, unsigned short Value, unsigned short Index, unsigned char Direction, unsigned short DataLength, unsigned char *Buffer[]);
int Disconnect (unsigned int Handle);
int main(){
char *partpath[2];
unsigned int *num;
unsigned int vid = 1110;
unsigned int pid = 45617;
unsigned int error = Search_For_Boards(vid, pid, num, partpath);
cout<<"Hello\n"<<error<<endl;
return 0;
}
And on compiling the code in the following command:
g++ C:\test.cpp -L "C:\Program Files\Analog Devices\USB Drivers" -lADI_CYUSB_USB4
I get the error
Undefined reference to Search_For_Boards(unsigned int, unsigned, int, unsigned int*, char**)
meaning apparently the function prototype is not correct.
Now all this is ASSUMING that i can use the DLL in a C++ program. Seeing the document for VB6 function declaration made me thinking if my assumption is wrong. So my 2 questions are :
1) Is my assumption correct?
2) If the assumption is correct, What is the blunder i am doing here? I feel like I linked the library properly and to my best declared the prototype according to what is described.

Cast function pointer to (void*)

I have a simple question which is breaking my mind.
On my solution, I'm working with a DLL that offers me the following function:
int RegisterCallback(TCallbackType CallbackType, void *pLLTProfileCallback, void *pUserData);
For more information, the parameter pLLTProfileCallback is a function type defined as:
typedef void (__stdcall *TNewProfile_s)(const unsigned char *pData,
unsigned int nSize, void *pUserData);
I'm trying to insert my function 'NewProfile' in this parameter as follows:
RegisterCallback(STD_CALL, (void*)NewProfile, m_pLLT1);
But it says: 'Error: invalid type conversion'.
The function definition for 'NewProfile' is:
void __stdcall NewProfile(const unsigned char* pucData, unsigned int uiSize, void* pUserData){...}
Where is my error exactly? What can I do in order to fix it?

using a callback function from a 3rd party api in your own class that is a dll

I am trying to write a class in a dll that uses a callback function from another dll. currently i can get the callback to work when i am calling it in a main function but i am having problems integrating it in my own dll.
I am using Hinstance in the regular project and the dll im compiling.
This works in a regular project:
void mycallback(float values[], __int64 timestamp, int status) {
//stuff
globalval[0]=values[0];
...
}
void main(){
...
void(*_callback)(float[], __int64, int);
_callback = &mycallback;
API_CALLBACK finalCallBack = (API_CALLBACK)_callback;
....
//I pass this callback in another function that the api uses later
}
However this fails when I try to port it in the initialise function in a class that I am compiling as a dll (I was trying to use bind function but #include was giving me errors (using visual studios 2015)
void MyClass::mycallback(float values[], __int64 timestamp, int status){
//stuff
myClassval[0]=values[0];
...
}
MyClass::Init(){
void(*_callback)(float[], __int64, int);=
_callback = &MyClass::mycallback;<---This line is giving me error
API_CALLBACK finalCallBack = (API_CALLBACK)_callback;
}
The error i get is "assigning to ' void(*)(float *,long long, int)' from incompaible type 'void(MyClass::*)(float *,long long,int)"
Is there a different way I should approach this? I am not sure how to handle this as I have only access to the function callbacks but not the source.
edit: I realise that casting mycallback as static would solve the problem but then I would run into the problem of being unable to store the value somewhere. or is there a good way to do this?
full code for further reference:
void main() {
//declare dll handler
HINSTANCE hinstLib;
FCALL _InitDevices,_ReleaseDevices;
FCALL_GETHMDINFO _getHMDinfo;
FCALL_HMDPRESENT _HMDPresent;
FCALL_STARTTRACKING _StartTracking;
BOOL fFreeResult;
//Load dll
hinstLib = LoadLibrary(TEXT("thirdparty.dll"));
bool* isHMDpresent = new bool;
void(*_hmdcallback)(float[], __int64, int);
_hmdcallback = &hmdcallback;
HMD_TRACK_CALLBACK hmdCallBack = (HMD_TRACK_CALLBACK)_hmdcallback;
//float handle = (float)hmdCallBack;
//if dll present
if (hinstLib != NULL)
{
//initialise devices
_InitDevices = (FCALL)GetProcAddress(hinstLib, "InitDevices");
if (NULL != _InitDevices)
{
std::cout<<(_InitDevices)()<<std::endl;
}
//start tracking
_StartTracking = (FCALL_STARTTRACKING)GetProcAddress(hinstLib, "StartTracking");
if (NULL != _StartTracking)
{
std::cout << (_StartTracking)(hmdCallBack,nullptr,nullptr,nullptr) << std::endl;
}
this is the function from the 3rd party dll
DLL_EXPORT typedef void(__stdcall *HMD_TRACK_CALLBACK)(float values[], __int64 timestamp, int status );
I am trying to convert the above and package it in another dll(a driver) with other functions from multiple dlls. The specific task i am trying to do now is to store an array from the callback of the dll i am using. In this case, one of the things im storing is values[]

Using a C++ library for a C application

I have a command line (+HTTP interface) audio application in C, which currently is being compiled with gcc on Mac OSX, but which I would like to keep this application linux compatible.
However, I would like to use the freeverb3 library. This is in C++. I would prefer not to convert all my code to C++. I don't (as far as I can see) need to call any C code from C++, nor will I need to use C++ objects in my C code. Simple method calls passing arrays of doubles plus a few ints as arguments will be all that I need in terms of interaction from my main application an the C++ code.
From some quick googling, it seems that I can write a C++ interface module, which can then expose some c compatible functions that I can call to make use of freeverb3. I"ve written a micro example to see how this might work. For this example, I have a dummy c++ file called test.cpp:
#include <iostream>
using namespace std;
class test_class
{
int a;
public:
int get_a();
void set_a( int v );
};
int test_class::get_a()
{
return a;
}
void test_class::set_a( int v )
{
a = v;
}
static test_class *c;
extern "C"
{
void init();
void set( int v );
int get();
}
void init()
{
c = new test_class();
}
void set( int v )
{
c->set_a( v );
}
int get()
{
return c->get_a();
}
I have a dummy c file that calls the functions:
#include <stdio.h>
/* Forward declaratoins for extern "C" functions in C++ code */
void init();
int get();
void set( int v );
/* C language code that references functions in C++ code */
int main()
{
init();
set( 55 );
printf( "value: %d\n", get() );
set( get() + 12 );
printf( "value: %d\n", get() );
return 0;
}
And, I have a makefile that creates an executable.
test: test.o user.o
g++ -o test user.o test.o
test.o: test.cpp
g++ -c test.cpp
user.o: user.c
gcc -c user.c
Is this a good way of using C++ code from C? Is there a better/more sophisticated/more traditional way of achieving this aim?
You might want to think about it the other way.
Write your higher level application in C++, invoke the C++ library where you want without complications and call all your current C modules from the C++ level.
IMHO, this is easier to achieve than doing the same with C as high level.
If you intend to use more than one C++ object from C you need to pass an extra instance pointer (this) to the C wrapper functions:
struct A {
A();
~A();
void set(int);
};
The C wrapper:
extern "C"
{
struct A* a_create(void);
void a_destroy(struct A*);
void a_set(struct A*, int);
}
You may also like to catch all C++ exceptions in the C wrapper functions and convert them to error codes.
Pass a pointer to your object instead of using a static variable.
C++ class:
class Foo
{
public:
void doStuff();
};
Common include file:
#ifdef __cplusplus
extern "C"
{
#endif
void Foo_doStuff(void* handle);
void* Foo_create();
void Foo_destroy(void* handle);
#ifdef __cplusplus
}
#endif
Wrapper functions
void Foo_doStuff(void* handle)
{((Foo*)handle)->doStuff();}
void* Foo_create()
{return new(nothrow)Foo;}
void Foo_destroy(void* handle)
{delete (Foo*)handle;}
Not sure whether this goes from C to C++ but it is well worth looking into Swig
Make an extern "C" wrapper in C++, e.g.
// myWrapper.h
#ifdef __cplusplus
extern "C"
{
#endif
void func1(void);
int func2(void);
void func3(char const *str_ptr, size_t len);
#ifdef __cplusplus
}
#endif
// myWrapper.cpp
#include "myWrapper.h"
#include "your_cpp_library.h"
void func3(char const *str_ptr, size_t len)
{
std::string s(str_ptr, str_ptr + len);
call_cpp_function(s);
}
// etc.
In your C code you #include "myWrapper.h" and call those functions. Make sure that:
The code in myWrapper.h stays in the common subset of C and C++
You do not do any cross-boundary resource allocation
The latter might work but it's best to avoid it to be safe. The latter point means that if memory is to be allocated, it must be allocated and freed by the same side; e.g. you can't have the C++ side call malloc and give a pointer to the C side, and then have the C side call free. You have to pass the pointer back to whoever allocated it and let them free it.
Important: as Alf says in a comment, you must have main() in C++ and use the C++ linker , when doing C - C++ inter-linking. This is not a big hurdle though; you can rename your C code's main() function to main2(), and have the C++ code do extern "C" int main2(); and call it.

Dynamically load a function from a DLL

I'm having a little look at .dll files, I understand their usage and I'm trying to understand how to use them.
I have created a .dll file that contains a function that returns an integer named funci()
using this code, I (think) I've imported the .dll file into the project(there's no complaints):
#include <windows.h>
#include <iostream>
int main() {
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop \\fgfdg\\dgdg\\test.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "cannot locate the .dll file" << std::endl;
} else {
std::cout << "it has been called" << std::endl;
return -1;
}
int a = funci();
return a;
}
# funci function
int funci() {
return 40;
}
However when I try to compile this .cpp file that I think has imported the .dll I have the following error:
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp||In function 'int main()':|
C:\Documents and Settings\User\Desktop\fgfdg\onemore.cpp|16|error: 'funci' was not declared in this scope|
||=== Build finished: 1 errors, 0 warnings ===|
I know a .dll is different from a header file so I know I can't import a function like this but it's the best I could come up with to show that I've tried.
My question is, how can I use the hGetProcIDDLL pointer to access the function within the .dll.
I hope this question makes sense and I'm not barking up some wrong tree yet again.
LoadLibrary does not do what you think it does. It loads the DLL into the memory of the current process, but it does not magically import functions defined in it! This wouldn't be possible, as function calls are resolved by the linker at compile time while LoadLibrary is called at runtime (remember that C++ is a statically typed language).
You need a separate WinAPI function to get the address of dynamically loaded functions: GetProcAddress.
Example
#include <windows.h>
#include <iostream>
/* Define a function pointer for our imported
* function.
* This reads as "introduce the new type f_funci as the type:
* pointer to a function returning an int and
* taking no arguments.
*
* Make sure to use matching calling convention (__cdecl, __stdcall, ...)
* with the exported function. __stdcall is the convention used by the WinAPI
*/
typedef int (__stdcall *f_funci)();
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\Documents and Settings\\User\\Desktop\\test.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
// resolve function address here
f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "funci");
if (!funci) {
std::cout << "could not locate the function" << std::endl;
return EXIT_FAILURE;
}
std::cout << "funci() returned " << funci() << std::endl;
return EXIT_SUCCESS;
}
Also, you should export your function from the DLL correctly. This can be done like this:
int __declspec(dllexport) __stdcall funci() {
// ...
}
As Lundin notes, it's good practice to free the handle to the library if you don't need them it longer. This will cause it to get unloaded if no other process still holds a handle to the same DLL.
In addition to the already posted answer, I thought I should share a handy trick I use to load all the DLL functions into the program through function pointers, without writing a separate GetProcAddress call for each and every function. I also like to call the functions directly as attempted in the OP.
Start by defining a generic function pointer type:
typedef int (__stdcall* func_ptr_t)();
What types that are used aren't really important. Now create an array of that type, which corresponds to the amount of functions you have in the DLL:
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
In this array we can store the actual function pointers that point into the DLL memory space.
Next problem is that GetProcAddress expects the function names as strings. So create a similar array consisting of the function names in the DLL:
const char* DLL_FUNCTION_NAMES [DLL_FUNCTIONS_N] =
{
"dll_add",
"dll_subtract",
"dll_do_stuff",
...
};
Now we can easily call GetProcAddress() in a loop and store each function inside that array:
for(int i=0; i<DLL_FUNCTIONS_N; i++)
{
func_ptr[i] = GetProcAddress(hinst_mydll, DLL_FUNCTION_NAMES[i]);
if(func_ptr[i] == NULL)
{
// error handling, most likely you have to terminate the program here
}
}
If the loop was successful, the only problem we have now is calling the functions. The function pointer typedef from earlier isn't helpful, because each function will have its own signature. This can be solved by creating a struct with all the function types:
typedef struct
{
int (__stdcall* dll_add_ptr)(int, int);
int (__stdcall* dll_subtract_ptr)(int, int);
void (__stdcall* dll_do_stuff_ptr)(something);
...
} functions_struct;
And finally, to connect these to the array from before, create a union:
typedef union
{
functions_struct by_type;
func_ptr_t func_ptr [DLL_FUNCTIONS_N];
} functions_union;
Now you can load all the functions from the DLL with the convenient loop, but call them through the by_type union member.
But of course, it is a bit burdensome to type out something like
functions.by_type.dll_add_ptr(1, 1); whenever you want to call a function.
As it turns out, this is the reason why I added the "ptr" postfix to the names: I wanted to keep them different from the actual function names. We can now smooth out the icky struct syntax and get the desired names, by using some macros:
#define dll_add (functions.by_type.dll_add_ptr)
#define dll_subtract (functions.by_type.dll_subtract_ptr)
#define dll_do_stuff (functions.by_type.dll_do_stuff_ptr)
And voilĂ , you can now use the function names, with the correct type and parameters, as if they were statically linked to your project:
int result = dll_add(1, 1);
Disclaimer: Strictly speaking, conversions between different function pointers are not defined by the C standard and not safe. So formally, what I'm doing here is undefined behavior. However, in the Windows world, function pointers are always of the same size no matter their type and the conversions between them are predictable on any version of Windows I've used.
Also, there might in theory be padding inserted in the union/struct, which would cause everything to fail. However, pointers happen to be of the same size as the alignment requirement in Windows. A static_assert to ensure that the struct/union has no padding might be in order still.
This is not exactly a hot topic, but I have a factory class that allows a dll to create an instance and return it as a DLL. It is what I came looking for but couldn't find exactly.
It is called like,
IHTTP_Server *server = SN::SN_Factory<IHTTP_Server>::CreateObject();
IHTTP_Server *server2 =
SN::SN_Factory<IHTTP_Server>::CreateObject(IHTTP_Server_special_entry);
where IHTTP_Server is the pure virtual interface for a class created either in another DLL, or the same one.
DEFINE_INTERFACE is used to give a class id an interface. Place inside interface;
An interface class looks like,
class IMyInterface
{
DEFINE_INTERFACE(IMyInterface);
public:
virtual ~IMyInterface() {};
virtual void MyMethod1() = 0;
...
};
The header file is like this
#if !defined(SN_FACTORY_H_INCLUDED)
#define SN_FACTORY_H_INCLUDED
#pragma once
The libraries are listed in this macro definition. One line per library/executable. It would be cool if we could call into another executable.
#define SN_APPLY_LIBRARIES(L, A) \
L(A, sn, "sn.dll") \
L(A, http_server_lib, "http_server_lib.dll") \
L(A, http_server, "")
Then for each dll/exe you define a macro and list its implementations. Def means that it is the default implementation for the interface. If it is not the default, you give a name for the interface used to identify it. Ie, special, and the name will be IHTTP_Server_special_entry.
#define SN_APPLY_ENTRYPOINTS_sn(M) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, def) \
M(IHTTP_Handler, SNI::SNI_HTTP_Handler, sn, special)
#define SN_APPLY_ENTRYPOINTS_http_server_lib(M) \
M(IHTTP_Server, HTTP::server::server, http_server_lib, def)
#define SN_APPLY_ENTRYPOINTS_http_server(M)
With the libraries all setup, the header file uses the macro definitions to define the needful.
#define APPLY_ENTRY(A, N, L) \
SN_APPLY_ENTRYPOINTS_##N(A)
#define DEFINE_INTERFACE(I) \
public: \
static const long Id = SN::I##_def_entry; \
private:
namespace SN
{
#define DEFINE_LIBRARY_ENUM(A, N, L) \
N##_library,
This creates an enum for the libraries.
enum LibraryValues
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_ENUM, "")
LastLibrary
};
#define DEFINE_ENTRY_ENUM(I, C, L, D) \
I##_##D##_entry,
This creates an enum for interface implementations.
enum EntryValues
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_ENUM)
LastEntry
};
long CallEntryPoint(long id, long interfaceId);
This defines the factory class. Not much to it here.
template <class I>
class SN_Factory
{
public:
SN_Factory()
{
}
static I *CreateObject(long id = I::Id )
{
return (I *)CallEntryPoint(id, I::Id);
}
};
}
#endif //SN_FACTORY_H_INCLUDED
Then the CPP is,
#include "sn_factory.h"
#include <windows.h>
Create the external entry point. You can check that it exists using depends.exe.
extern "C"
{
__declspec(dllexport) long entrypoint(long id)
{
#define CREATE_OBJECT(I, C, L, D) \
case SN::I##_##D##_entry: return (int) new C();
switch (id)
{
SN_APPLY_CURRENT_LIBRARY(APPLY_ENTRY, CREATE_OBJECT)
case -1:
default:
return 0;
}
}
}
The macros set up all the data needed.
namespace SN
{
bool loaded = false;
char * libraryPathArray[SN::LastLibrary];
#define DEFINE_LIBRARY_PATH(A, N, L) \
libraryPathArray[N##_library] = L;
static void LoadLibraryPaths()
{
SN_APPLY_LIBRARIES(DEFINE_LIBRARY_PATH, "")
}
typedef long(*f_entrypoint)(long id);
f_entrypoint libraryFunctionArray[LastLibrary - 1];
void InitlibraryFunctionArray()
{
for (long j = 0; j < LastLibrary; j++)
{
libraryFunctionArray[j] = 0;
}
#define DEFAULT_LIBRARY_ENTRY(A, N, L) \
libraryFunctionArray[N##_library] = &entrypoint;
SN_APPLY_CURRENT_LIBRARY(DEFAULT_LIBRARY_ENTRY, "")
}
enum SN::LibraryValues libraryForEntryPointArray[SN::LastEntry];
#define DEFINE_ENTRY_POINT_LIBRARY(I, C, L, D) \
libraryForEntryPointArray[I##_##D##_entry] = L##_library;
void LoadLibraryForEntryPointArray()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_POINT_LIBRARY)
}
enum SN::EntryValues defaultEntryArray[SN::LastEntry];
#define DEFINE_ENTRY_DEFAULT(I, C, L, D) \
defaultEntryArray[I##_##D##_entry] = I##_def_entry;
void LoadDefaultEntries()
{
SN_APPLY_LIBRARIES(APPLY_ENTRY, DEFINE_ENTRY_DEFAULT)
}
void Initialize()
{
if (!loaded)
{
loaded = true;
LoadLibraryPaths();
InitlibraryFunctionArray();
LoadLibraryForEntryPointArray();
LoadDefaultEntries();
}
}
long CallEntryPoint(long id, long interfaceId)
{
Initialize();
// assert(defaultEntryArray[id] == interfaceId, "Request to create an object for the wrong interface.")
enum SN::LibraryValues l = libraryForEntryPointArray[id];
f_entrypoint f = libraryFunctionArray[l];
if (!f)
{
HINSTANCE hGetProcIDDLL = LoadLibraryA(libraryPathArray[l]);
if (!hGetProcIDDLL) {
return NULL;
}
// resolve function address here
f = (f_entrypoint)GetProcAddress(hGetProcIDDLL, "entrypoint");
if (!f) {
return NULL;
}
libraryFunctionArray[l] = f;
}
return f(id);
}
}
Each library includes this "cpp" with a stub cpp for each library/executable. Any specific compiled header stuff.
#include "sn_pch.h"
Setup this library.
#define SN_APPLY_CURRENT_LIBRARY(L, A) \
L(A, sn, "sn.dll")
An include for the main cpp. I guess this cpp could be a .h. But there are different ways you could do this. This approach worked for me.
#include "../inc/sn_factory.cpp"