I have following function defined in one dll:
__declspec( dllexport ) int __stdcall
mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile )
I need to write one process to call the above function.
I am doing it first time,I do not have much idea.
I have written the following code
#include <windows.h>
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <limits.h>
extern __declspec( dllexport ) int __stdcall mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile );
typedef INT (*MJSCALL) (char *,DWORD, char *, char *);
int main()
{
char *a,*b,*c;
a=NULL;
b=NULL;
c=NULL;
DWORD aa =1;
int i;
HMODULE hLib;
MJSCALL ADD;
hLib=LoadLibrary("f3cucall.dll");
if(hLib==NULL)
{
return 1;
}
ADD=(MJSCALL)GetProcAddress(hLib,"mjscall");
if (ADD==NULL)
{
return 1;
}
(ADD)(a,aa,b,c);
return 0;
}
The "(ADD)(a,aa,b,c);" is causing the problem.
Can somebody help me out?
I think you mixed two things up:
the __declspec(dllexport) MSVC keyword exports functions from a DLL (tells the linker to do so), and the __declspec(dllimport) imports functions from a DLL. This is done at loading time, the linker will create all the necessary code to load the DLL and resolve the symbol. In fact, it adds some code to the exe to let the OS load the DLL. You can use functions declared with __declspec(dllimport) just like any normal internal function.
If you want to use this approach, you need the DLL's lib file, since it contains information for the linker to resolve the symbolic name. It doesn't actually contain code, only these information on the DLL for the linker. Additionally, you have to tell the linker that the function you want to use is located at a DLL, using the magic __declspec(dllimport) before the function declaration. That's why you provide a .lib and a header file (containing these declarations) with your DLL if you want to do it this way. You should rebuild the project that uses the DLL when you change the DLL, as the .lib file may have changed.
You can use the same header file in your DLL project and the projects that import from this DLL:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API void printMe(int);
The MyDLL_API get resolved to either __declspec(dllexport) (in the DLL project, where you define the MYDLL_EXPORTS in the project settings) or __declspec(dllimport) (in all projects that use the dll). This way, you only need one header file for the DLL.
Another method of calling DLL functions is to use LoadLibrary and GetProcAdress. These two are used to load a DLL at runtime. The main difference between loading a DLL at loading time and at runtime is that you have some control over loading the DLL at runtime, whereas the OS will do the job when the DLL is to load at loading time (e.g. show a message box if the DLL cannot be found and do not run the process).
Related
I have a dll created using MSVC. The header file and a .def file are also present.
Here is what is exported from the dll (simple.def):
EXPORTS
simple_initialize
simple_step
simple_terminate
In1
Gain
Increment
I have a simple application that is trying to access the functions and variables inside the dll (have the .lib file as well). The MSVC project files have the necessary files provide and the application builds correctly. Here's the application code:
#include <stddef.h>
#include <stdio.h>
#include "simple.h"
#include "rtwtypes.h"
void main(void)
{
int i;
simple_initialize();
for (i = 0; i < 10; i++)
{
simple_step();
}
simple_terminate();
}
This code seems to be working fine, however, if I try to write to any of the global variables (In1, Gain or Increment) from the dll it results in a crash.
After researching I realized that the only way I can make it work is by adding
__declspec(dllimport) real_T In1;
AND
commenting out this line from the header file:
extern real_T In1;
If I do not comment this line, then I get following error:
Error C2370 'In1': redefinition; different storage class SimpleTest \SimpleTest.c 8
We have a repo that contains library functions for example (gcc is used to compile and link).
//print.h
#ifndef __PRINT_H_
#define __PRINT_H_
#define MAX_ARRAY 10
void print_hex(int cal[]);
#endif
// print.c
#include <stdio.h>
void print_hex(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf("%i\n",val[I]);
}
}
The above is compiled into a libprint.a.1.0.0. My app is then compiled using this library
//main.c
#include "print.h"
int main(int argc, int arg[]) {
int vals[MAX_ARRAY];
memset(vals,8,MAX_ARRAY*sizeof(int));
print_hex(vals);
return 0;
}
And everything is fine and works (assuming have typed the above out correctly). But then someone decides to make a change in the library where someone Makes the following change.
//print.h
...
#define MAX_ARRAY 50
...
The library is recompiled to libprint.a.1.1.0
This new static library is now used when compiling and linking our main.c. However, the new print.h was not copied to the include directory so the main.c is using an old print.h where MAX_ARRAY is smaller.
Now in this case we might get any behaviour as the print function runs off the end of the passed in array. As a user of the library there is no way to necessarily know that the header file is wrong until I compile and run the application, or perhaps even hours of running when the program starts to go crazy.
What is the standard way to avoid this issue?
Is there a way to add a version to a header file to ensure the correct library is linked?
I realise I could do this by creating a new function in print.c called get_version(), and use that in main.c to check against some defines in print.h to ensure veracity but I was wondering if there was a way without the user application having to specifically check library and header versions at run time.
Yes. And don't do it.
The libfuse library uses a macro FUSE_USE_VERSION that should be defined by the client to differentiate between different versions. Internally it works similar to feature_test_macros.
So in your library it would look like:
print.h:
#ifndef __PRINT_H_
#define __PRINT_H_
#if PRINT_USE_VERSION == 1
#define MAX_ARRAY 10
void print_hex_version_1(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_1(val);
}
#elif PRINT_USE_VERSION == 2
#define MAX_ARRAY 50
void print_hex_version_2(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_2(val);
}
#else
#error unknown PRINT_USE_VERSION
#endif
#endif
print_version_1.c:
#define PRINT_USE_VERSION 1
#include <stdio.h>
void print_hex_version_1(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
print_version_2.c:
#define PRINT_USE_VERSION 2
#include <stdio.h>
void print_hex_version_2(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
Or similar, hope you'll you get the idea. Using this method you can distribute all possible versions of your library at once. And clients can link against multiple versions of your library. Which ends up being spaghetti code, unstable, unreliable, unfixable and unmaintainable.
On a global scale, it makes no sense. Just create a api that isn't dependent on a macro definition and take the array size as an argument. Check if the size of the array is equal to some predefined value and notify your client with error code that he did something wrong.
Alongside main.c file, I have following my_custom_data_structure.c file in my project. My my_custom_data_structure.c file contains a lot of variables, functions, etc.
I am using #include "my_custom_data_structure.c" directive in main.c.
Problem
I would like to import only single function called foo from my_custom_data_structure.c. I don't need all the variables and functions, which are declared in my_custom_data_structure.c file.
Any insights appreciated.
File structure
-
|- main.c
|- my_custom_data_structure.c
Content of my_custom_data_structure.c
#include <stdio.h>
int DELAY = 20;
int SPEED = 7;
char GRANULARITY_CHAR = 'g';
unsigned int RANGE = 3;
void foo(){
// TODO: In future, this function will print SPEED.
printf("foo works!");
}
/*
The rest of this file is filled by a lot
of code, which is not needed for main.c
*/
Content of main.c
#include <stdio.h>
#include "my_custom_data_structure.c"
int DELAY = 3;
int main(){
foo();
printf("Delay is %d", DELAY);
return 0;
}
UPDATED: Added working example
The usual way is to compile them separately. So you have your main.c, and your extra.c, and you should create a extra.h (and include it in main.c).
In this extra.h, put in declarations for anything that is to be exported from your extra.c file.
For example any functions that should be available to other files. All other functions should be declared/defined only in your extra.c as static, so that they are not available as symbols to be linked when main.c is compiled.
Normally, you don't include source files (.c) inside other source files (or inside headers). It's possible (and occasionally necessary), but it isn't usual.
Unless you've designed the my_custom_data_structure.c to allow you to specify which functions are to be compiled, you get everything in the file. For example, you could use:
#ifdef USE_FUNCTION1
void function1(void *, …)
{
…
}
#endif /* USE_FUNCTION1 */
around each function, and then arrange to
#define USE_FUNCTION1
before including the source, but that's not usually a good way of working. It's fiddly. You have to know which functions you use, and which other functions those need, and so on, and it is vulnerable to changes making the lists of USE_FUNCTIONn defines inaccurate. Of course, the source code might have blocks of code like:
#ifdef USE_FUNCTION1
#define USE_FUNCTION37
#define USE_FUNCTION92
#define USE_FUNCTION102
#endif /* USE_FUNCTION1 */
so that if you say you use function1(), it automatically compiles the other functions that are required, but maintaining those lists of definitions is fiddly too, even when the definitions are USE_MEANINGFUL_NAME instead of a number.
Create a header (my_customer_data_structure.h) declaring the functions and any types needed, and split the implementation into many files (mcds_part1.c, mcds_part2.c, …).
Compile the separate implementation files into a library (e.g. libmcds.a), and then link your program with the library. If it's a static library, only those functions that are used, directly or indirectly, will be included in the executable.
I am trying to import a function from an unmanaged DLL into a C project by creating a .def file specifying the function I need to use. I am practicing on the WinAPI function MessageBoxA from user32.dll. It is an stdcall function, like the other WinAPI functions.
Here's how I create my .def file:
LIBRARY user32.dll
EXPORTS
_MessageBoxA#16
Then I create a .lib from it like this: lib /def:"C:\Path\to\def\user32.def" /
out:"C:\path\to\project\user32-mb.lib" which successfully creates user32-mb.lib and user32-mb.exp. Then, in my C project, I do the following:
#pragma comment(lib, "user32-mb.lib")
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
EXTERNC __declspec(dllexport) int __stdcall MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
void main(){
MessageBoxA(0, "MessageBox test", "MessageBox test", 0x00000030L);
}
However, upon linking, it gives the following error:
error LNK2019: unresolved external symbol _MessageBoxA#16 referenced in function _main
However, when I change the declaration in the .def to this:
LIBRARY user32.dll
EXPORTS
MessageBoxA
And change the function prototype in my C code to cdecl instead of stdcall:
EXTERNC __declspec(dllexport) int __cdecl MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
The message box actually appears, but right on closing, it throws an error:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Which indicates that calling it with cdecl is also a bad idea since it requires stdcall after all.
The question is, what should I change in the .def file or in my project to avoid both errors and to import and call an stdcall function properly?
You need to change __declspec(dllexport) to __declspec(dllimport), as you are importing functions from a DLL, not exporting them:
EXTERNC __declspec(dllimport) int __stdcall MessageBoxA(void *hWnd, char *lpText, char *lpCaption, int uType);
^^
You need to use dllimport rather than dllexport, but in this case you should remove the __declspec(...) altogether.
And you need to specify the correct name for the function which is MessageBoxA.
LIBRARY USER32.dll
EXPORTS
MessageBoxA
Also it would be remiss of me not to point out that the correct main declaration is
int main(void)
I am still not entirely sure why, but removing the _ adding the ordinal to the function name my .def file fixed everything. My solution is:
LIBRARY USER32.dll
EXPORTS
MessageBoxA#16 #2093
Function definition:
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef const char *LPCSTR;
typedef unsigned int UINT;
EXTERNC __declspec(dllimport)
int
__stdcall
MessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);
This page indicates that winuser.h is the header. From there, you can see some macros are used, including WINUSERAPI and WINAPI. WINUSERAPI is conditionally #define-d at the beginning of that header. WINAPI can be found in the winbase.h header, where it can be seen to be tied to a calling convention, depending on the platform.
But a better question is: Why are you using dllexport and not dllimport?
I'm busy getting to know a tiny bit of C/C++, and interop with C#. I've checked several examples of creating a simple Win32 DLL and using this from C#, but when I try and call into my DLL, I get the runtime error: "Unable to find an entry point named TestFunc". My DLL looks like this, and I created it from a Win32 DLL project, with the empty project option:
Header:
__declspec(dllexport) int TestFunc(char *, char *, char *);
Code file:
#include "stdafx.h"
#include "TestLib.h"
__declspec(dllexport) int TestFunc(char *arg1, char *arg2, char *arg3)
{
char str1[] = "Brady Kelly";
char str2[] = "Hello World";
char str3[] = "1234567890";
strcpy(arg1, str1);
return 128;
}
What am I doing wrong?
Is your function compiled using C or C++ bindings? You don't specify, but it looks to me like there is a possibility that you are using the C++ compiler - the compiler uses very different name mangling from the C compiler and you will not be able to find the name "TestFunc" as simply as if you were using the C compiler or using C name mangling rules.
To simply tell the C++ compiler to use C name mangling rules, use this in the header file:
extern "C"
{
__declspec(dllexport) int TestFunc(char *, char *, char *);
}
Also, you only need the declspec in front of the function declaration (in the header file), not the definition. A useful tool for examining what is exported from the DLL, and what the DLL depends on is Dependency Walker.
Actually since you have tagged this question as C, I'd suggest a minor change from what 1800 INFORMATION's solution:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef EXPORT_MODE
#define METHODTYPE __declspec(dllexport)
#else
#define METHODTYPE __declspec(dllimport)
#endif
#ifdef __cplusplus
}
#endif
/*! _The_ method */
METHODTYPE int TestFunc(char *, char *, char *);
This will let you use the same header both in clients' code and your code.
NB: Dependency Walker is no longer bundled with VS2008. You must download it if you are using VS2008.