473,399 Members | 2,146 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

Global DLL Import of Functions

The problem:
1) I'm not a programmer, most of the time I'm a physicist, but I do numerical simulation.

2) I have a DLL that I want to use functions from. I have the .h file associated with the DLL, but no .def or library that I can use for static linking.

I am trying to implement the GMP (GNU multiprecision library) in a large simulation code that I’ve been running on a PC, written in standard C. I’ve been using MetroWerks CodeWarrior IDE for the compiling and debugging.

The libraries are actually from the GNU project, but unfortunately, only the unix versions of the static library are available, and I’ve not managed to find a way to convert them for use in CodeWarrior. I did manage to find a version of the DLL (used by both Maple and Matlab), and a DLL viewer that lets me look at what routines are in the DLL. Using the GMP manual, I was able to get the function definitions. With this data, I’m trying to import the functions in GMP.dll into the simulation code.

I tested the routines by writing a small piece of code that imported the functions as shown below. In this simple routine I could load and execute the functions. The problem is that I want to use the functions in MANY routines distributed in six other files in the simulation code. I would like to import the functions from the DLL so that they are global in scope.

I can link the functions successfully using the following code, inside main.c,

(only one function is shown for brevity..)
Expand|Select|Wrap|Line Numbers
  1. #include <gmp.h>
  2.  
  3. typedef void     (*importFunction ) (unsigned long int);        // mpf_set_default_prec 
  4. ..
  5. ..
  6. int main(void)
  7. {
  8. ..
  9. ..
  10. importFunction mpf_set_default_prec; //---line(1)
  11. //
  12. // Load the DLL
  13. //          
  14. HINSTANCE hinstLib = LoadLibrary("gmp.dll");
  15.  if(hinstLib == NULL)
  16.  {
  17.             printf("ERROR: unable to load gmp.dll\n");
  18.             return  1;
  19.  }
  20.  
  21.  
  22.  mpf_set_default_prec = ((importFunction)GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
  23.  ..
  24. }
My question is this. The above code works, but only allows me to define the function in the present routine. I want to use the imported functions in several function in my code.

When I try to make the definition of mpf_set_default_prec global, by moving line 1 outside the definition of main, I get the following error,

Error : identifier '__gmpf_set_default_prec(unsigned long)' redeclared
was declared as: 'void (unsigned long)'
now declared as: 'void (*)(unsigned long)'
main.c line 17 importFunction mpf_set_default_prec;

Error : not an lvalue
main.c line 44 mpf_set_default_prec = ((importFunction)GetProcAddress(hinstLib, "__gmpf_set_default_prec"));

So, do I have to link to the DLL and load the functions within it inside each function that I want to use the imported functions in? Or is there some way to link to the library once and make the function available globally?

Any help would be very greatly appreciated.

Andre
Oct 24 '07 #1
4 3788
RedSon
5,000 Expert 4TB
Thanks for editing your code to only display the relevant parts, but in the future please enclose your posted code in [code] tags (See How to Ask a Question).

This makes it easier for our Experts to read and understand it. Failing to do so creates extra work for the moderators, thus wasting resources, otherwise available to answer the members' questions.

Please use [code] tags in future.

MODERATOR
Oct 24 '07 #2
weaknessforcats
9,208 Expert Mod 8TB
mpf_set_default_prec = ((importFunction)GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
..
What I recommend is to declare a function pointer with the same name as the function in the DLL. Function pointers have to be declared with the same arguments and return types as the actual function.

You could declare these function pointers globally so they would be accessible anywhere in the program.

Take the function "__gmpf_set_default_prec" that you used to call GetProcAddress(). GetProcAddress() returns a FARPROC so your code should look like:
Expand|Select|Wrap|Line Numbers
  1. FARPROC fp = GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
  2.  
Next, you typecast fp so you can assign it to the correct function pointer. For this example I will assume this function has and int and a double argument and returns a double (I realize I am making this up for purposes of illustration).
Expand|Select|Wrap|Line Numbers
  1. //
  2. //Declare a global function pointer:
  3. //to a function that has and int and a double argument
  4. //and returns a double.
  5. //Give it the name of the actual function in the dll.
  6. double (*__gmpf_set_default_prec)(int, double);
  7.  
  8. int main()
  9. {
  10.      //do the load library, etc;
  11.  
  12. FARPROC fp;
  13. //
  14. //Get the address of the function from the DLL
  15. fp = GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
  16. //
  17. //Then typecast the FARPROC to your function pointer
  18. //
  19. __gmpf_set_default_prec = double (*)(int, double)fp;
  20.  
  21. //Now the address of __gmpf_set_default_prec() inside the DLL is also inside
  22. //the function pointer __gmpf_set_default_prec.
  23.  
  24. //From here on you call the function using the function pointer:
  25.  
  26. double result = __gmpf_set_default_prec(3, 1.5);
  27.  
  28. //And it looks like you called the function directly.
  29.  
  30. }
  31.  
Oct 25 '07 #3
What I recommend is to declare a function pointer with the same name as the function in the DLL. Function pointers have to be declared with the same arguments and return types as the actual function.

You could declare these function pointers globally so they would be accessible anywhere in the program.

Take the function "__gmpf_set_default_prec" that you used to call GetProcAddress(). GetProcAddress() returns a FARPROC so your code should look like:
Expand|Select|Wrap|Line Numbers
  1. FARPROC fp = GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
  2.  
Next, you typecast fp so you can assign it to the correct function pointer. For this example I will assume this function has and int and a double argument and returns a double (I realize I am making this up for purposes of illustration).
Expand|Select|Wrap|Line Numbers
  1. //
  2. //Declare a global function pointer:
  3. //to a function that has and int and a double argument
  4. //and returns a double.
  5. //Give it the name of the actual function in the dll.
  6. double (*__gmpf_set_default_prec)(int, double);
  7.  
  8. int main()
  9. {
  10.      //do the load library, etc;
  11.  
  12. FARPROC fp;
  13. //
  14. //Get the address of the function from the DLL
  15. fp = GetProcAddress(hinstLib, "__gmpf_set_default_prec"));
  16. //
  17. //Then typecast the FARPROC to your function pointer
  18. //
  19. __gmpf_set_default_prec = double (*)(int, double)fp;
  20.  
  21. //Now the address of __gmpf_set_default_prec() inside the DLL is also inside
  22. //the function pointer __gmpf_set_default_prec.
  23.  
  24. //From here on you call the function using the function pointer:
  25.  
  26. double result = __gmpf_set_default_prec(3, 1.5);
  27.  
  28. //And it looks like you called the function directly.
  29.  
  30. }
  31.  
This almost works.
I had to remove the definititions in the header file to prevent redefinitions, but I was able to get the functions working in the routine main.

I still have a problem however. If I try to use the global function pointers in other code files I get either a "Access Violation at address xxxx".

It seems that I'm not actually getting a global definition of the functions. If I write another function in the main.c file, it can access the functions imported from the library properly. If I move that same function to another file, compile and link, I get the error.

If I use a function prototype in the other file, I get multiple definitions of the pointer and the same error...

How do I fix this?

Thanks,
Andre
Oct 25 '07 #4
weaknessforcats
9,208 Expert Mod 8TB
OK, here's what I did:

1) I created a source file with this code:
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. extern void (__stdcall *__gmpf_set_default_prec)(int arg);
  5.  
  6. void TestCase()
  7. {
  8.     cout << "Entering TestCase()" << endl;
  9.     __gmpf_set_default_prec(25);
  10.      cout << "Leaving TestCase()" << endl;
  11.  
  12. }
  13.  
I made up that your function has an int argument.

As you can see I have an extern to a a function pointer that:
1) must be an __stdcall
2) takes an int argument
3) happens to be the same name as the function in the dll.

In the main() (in another source file) I load the library and use GetProcAddress to find the function in the dll, typecast the return from GetProcAddress to the function pointer and then call the function.

Afterwards I call the same function in the TestCase() function in the other file.
Here is my main():
Expand|Select|Wrap|Line Numbers
  1. using namespace std;
  2.  
  3. void (__stdcall *__gmpf_set_default_prec)(int arg);
  4. void (__stdcall *DisplayFromDll)();
  5. void TestCase();
  6.  
  7. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  8. {
  9.  
  10.  
  11.     cout << "Calling functions from a dll" << endl;
  12.  
  13.     //First, load the dll into memory
  14.     //C:\Scratch\Instructor\Debug
  15.     HMODULE theDll = LoadLibrary(TEXT("C:\\Scratch\\Instructor\\Debug\\ADll.dll"));
  16.     if (!theDll)
  17.     {
  18.         cout << "The dll failed to load" << endl;
  19.         return 1;
  20.     }
  21.  
  22.     //Second, get the address of the desried function from the dll
  23.     FARPROC addr = GetProcAddress(theDll, "__gmpf_set_default_prec");
  24.     if (!addr)
  25.     {
  26.  
  27.         //Look up the error in the system errors list
  28.         unsigned int what = GetLastError();
  29.         if (what == ERROR_PROC_NOT_FOUND)
  30.         {
  31.             cout << "Function not found in the dll" << endl;
  32.         }
  33.         else
  34.         {
  35.             cout << "Error: " << what << endl;
  36.         }
  37.         return 2;
  38.     }
  39.     cout << "The function has been located in the dll" << endl;
  40.     //Declare a function pointer that can accept the address of the function.
  41.     //You will need to know the function prototype to do this.
  42.     //Dll function prototypes should be provided by the vendor of the dll
  43.     //Type-cast the address returned from GetProcAddress to the function pointer type
  44.     __gmpf_set_default_prec = reinterpret_cast<void (__stdcall *)(int)>  (addr);
  45.  
  46.     //Now use the function pointer to call the function:
  47.     __gmpf_set_default_prec(3);
  48.  
  49.     TestCase();
  50.  
  51.     //Finally, unload the dll from memory
  52.     FreeLibrary(theDll);
  53.  
  54.     return 0;
  55. }
  56.  
The function pointer is gloabal so the TestCase in the other file can access it.

As far as the DLL goes, this is the DEF file:
Expand|Select|Wrap|Line Numbers
  1. ;BEGIN ADLL.DEF FILE
  2. ;This DEF file is required becuase the argument to GetProcAddress()
  3. ;for the function is a C-string and it will never be equal to the
  4. ;C++ mangled name for the function
  5. ;This DEF file maps the mangled name to a name that can be used with GetProcAddress()
  6. ;Note also: Change project settings in Visual Studio to send the LINK this def file.
  7. ;Visual Studio.NET: Project Properties/Linker/Input/Module Definition File/...Path to the def file\Adll.def
  8. LIBRARY ADll 
  9. EXPORTS 
  10. ;Exported Name    C++ Mangled Name
  11. AreaOfSquare   =  ?AreaOfSquare@@YGHHH@Z
  12. DisplayFromDll =  ?DisplayFromDll@@YGXXZ
  13. __gmpf_set_default_prec = ?__gmpf_set_default_prec@@YGXH@Z
  14. ;END DEF FILE 
  15.  
The DLL itself is:
Expand|Select|Wrap|Line Numbers
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. void __stdcall DisplayFromDll()
  5. {
  6.     cout << "This function was called from ADLL.dll" << endl;
  7. }
  8.  
  9. int __stdcall AreaOfSquare (int len, int wid)
  10. {
  11.     return len * wid;
  12. }
  13. void __stdcall __gmpf_set_default_prec(int arg)
  14. {
  15.         cout << "Hello! The magic number is " << arg << endl;
  16. }
  17.  
The only stumbling block I had was failing to followe the instruction in the def file to add the path top the def file as a module definition for the linker. After I did that, then everything works.
Oct 28 '07 #5

Sign in to post your reply or Sign up for a free account.

Similar topics

88
by: Tim Tyler | last post by:
PHP puts most of its functions into a big flat global namespace. That leads to short function names - but creates a namespace minefield for programmers. Lots of the functions are legacies from...
13
by: David Rysdam | last post by:
Getting no answer yesterday, I've done some investigation and I obviously don't understand how python namespaces work. Here's a test program: #!/usr/bin/python b = 2 def sumWithGlobal(a):...
7
by: Aaron Deskins | last post by:
I'm trying to write program with a main.py and several functions distributed in auxiliary *.py files. I've looked through the archives on the 'global' keyword, but I'm still not sure how to get...
14
by: Alan Silver | last post by:
Hello, I have spent ages trawling through Google, looking for information about global functions in ASP.NET and I'm still not clear about the best way to go about this (or not). I am writing...
16
by: didier.doussaud | last post by:
I have a stange side effect in my project : in my project I need to write "gobal" to use global symbol : .... import math .... def f() : global math # necessary ?????? else next line...
12
by: reubendb | last post by:
Hello, I am new to Python. I have the following question / problem. I have a visualization software with command-line interface (CLI), which essentially is a Python (v. 2.5) interpreter with...
3
by: barronmo | last post by:
I'm getting an error msg I don't understand, "global name EMR_globals is not defined", and could use some help. I've separated the application I'm building into several modules. One of the...
0
by: Gary Herron | last post by:
Jacob Davis wrote: Yuck, YUCK, YUCK! You are breaking *so* many good-programming-practices, I hardly know where to start. First off: A python global is not what you think. There are *no*...
4
by: RgeeK | last post by:
I have a main module doStuff.py and another module utility.py. At the start of doStuff.py I call import utility.py Then I also proceed to initiallize some global variables sName = "" ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.