12-15-2009 03:43 AM
Greetings,
in the CVI Build Options I have checked 'require function protoypes' because I consider this a useful safety measure. The project includes some 30 files which all work well except one which relies on functions provided by an external DLL.
Accordingly, these function calls are not prototyped and I receive the 'missing prototype' error.
I could imagine two solutions:
- find a way to protype external functions
- exclude one file from this build option
I would prefer the first version and doubt that the second option is possible.
So here is how I use the DLL:
a typical function call looks like this: ( *ext_dll_Continue ) ( instrument );
where the address is obtained via ext_dll_Continue = GetProcAddress ( ext_dll, "Continue" );
and ext_dll_Continue has been defined as
FARPROC ext_dll_Continue = NULL;
Assistance of how to prototype such a function call would be most welcome - Thanks!
Wolfgang
Solved! Go to Solution.
12-15-2009 03:36 PM - edited 12-15-2009 03:38 PM
Wolfgang -
Doesn't this beg the question - how can you be using a function in a DLL if you don't know its prototype? Just because you are dynamically loading it (and not using an export header file or import library) that doesn't mean you don't have to know the function prototype. Whoever created the external DLL needs to tell you how to call the functions in it.
You indicated you sortof know how to call the Continue function: If you in fact know the return type, and the function name, and the order, number, and type of paramters, then you can create your own prototype obviously.
You might try looking inside the DLL with a tool to see if you can glean info on the included functions. Depends.exe will tell you the names of all the included functions, and can undecorate C++ functions that have been mangled to encode the order, number, and type of parameters. But the DLL does not have (except maybe indirectly through C++ mangling) the order, number, and type of parameters visible in any way that can be inspected.
Menchar
12-16-2009 01:50 AM
Dear Menchar,
Thank you for addressing this question!
My question probably is more basic than you might have thought: Indeed I do have an include file for the functions provided by the external DLL, e.g.
void APIENTRY Continue ( int System );
Now, in order to use this function in my program, first I get the address of this function using ext_dll = LoadLibrary ( "xxx" ) and dll_Continue = GetProcAddress ( ext_dll, "Continue" );
Now I do have the address and know how to call the function ( ( *ext_dll_Continue ) ( instrument ) with instrument being an integer ) but the line
( *ext_dll_Continue ) ( instrument )
has not been prototyped yet and accordingly CVI may complain.
GetProcAddress returns a function pointer of type FARPROC, therefore I have initialized this pointer to FARPROC ext_dll_Continue = NULL;
I cannot use something like
void ext_dll_Continue ( int );
in analogy to the provided DLL include file because then operands of GetProcAddress won't match.
So I would rephrase my question: I do not know how to prototype this function call...
Thanks,
Wolfgang
12-16-2009 03:22 AM
I do this kind of thing all the time in CVI. I use the following general approach:
typedef __declspec (dllexport) int (*pfint1) (int); // This definition matches the one in the .h file
pfint1 Continue; // This will be our reference to the external function
Continue = (pfint1) GetProcAddress (dllHan, "Continue"); // dllHan presumed valid here
val = Continue (param); // Call the function in the dll
This all works without warnings. (Prototypes required box ticked.) Obviously you can introduce different typdefs for the various different prototype patterns you plan to use.
JR
12-16-2009 03:50 AM
Thank you! I wasn't aware of the keyword __declspec(dllexport)
Wolfgang
12-16-2009 04:10 AM
JR,
there is a small but basic question left - where do I put the typedef __declspec (dllexport) int (*pfint1) (int);?
Warning: Import/export modifier in type definintion is ignored.
Thanks, Wolfgang
BTW, if NI reads this post: there is a typo in the warning message... >> definintion <<
12-16-2009 04:19 AM - edited 12-16-2009 04:22 AM
The __declspec (dllexport) component that I used was simply copied from the header file that my particular dll had. You should start with the definition in your header file and work from there. The key is to make the definitions the same and thus avoid compiler complaints!
JR
EDIT: forgot to answer the question! I usually put all my typedefs at the beginning of the c file, after the #includes and #defines but before any variables. In larger programs I put them in a separate header file.
12-16-2009 07:59 AM
Hi Wolfgang,
an example for calling a DLL in CVI dynamically you can find here:
http://zone.ni.com/devzone/cda/epd/p/id/6151
12-16-2009 09:06 AM
At the risk of belaboring this any further, I would just like to add a couple things. The warning you are receiving Wolfgang is new to CVI 2009, and is an indication that the __declspec(dllexport) decoration is unnecessary in the typedef statement. That decoration is used to mark the function as exported from the dll, however, has no impact in your module that is calling the function in the dll. Thanks for pointing out the typo in our warning though - we'll get that fixed.
You can prototype a function in the following three ways (you'll have to use GetProcAddress with the first two), considering a function with this prototype:
As stated by JR, just minus the __declspec(dllexport):
Without creating a typedef, thus creating a global (if declared globally) pointer to a function that takes an int and returns an int:
Or, if you have access to the lib of the dll, you can simply prototype it as extern, and then call it as usual, as the function will be picked up in the link:
Finally - if you have a header file for the dll, you should try opening the header file in CVI, and then selecting the Options»Create DLL Import Source menu item. You will then browse to the dll of interest, and all of this dynamic loading will be done for you in a new source file. It can also be helpful to see how some more complex functions would be prototyped.
NickB
National Instruments
12-16-2009 09:22 AM
ey, so many nice and helpful feedbacks, thanks a lot!
Wolfgang