编写调用过程中dll调用的问题
我在一个 dll 中定义了以下函数:
__declspec( dllexport ) int __stdcall
mjscall(char *cmd, DWORD wtime, char *stdoutfile, char *stderrfile )
我需要编写一个进程来调用上述函数。 我是第一次做,没有太多想法。 我编写了以下代码
#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;
}
“(ADD)(a,aa,b,c);”导致了问题。 有人可以帮我吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你混淆了两件事:
__declspec(dllexport)
MSVC 关键字从 DLL 导出函数(告诉链接器这样做),__declspec(dllimport)
从 DLL 导入函数。这是在加载时完成的,链接器将创建所有必要的代码来加载 DLL 并解析符号。事实上,它会在exe中添加一些代码来让操作系统加载DLL。您可以像使用任何普通内部函数一样使用通过 __declspec(dllimport) 声明的函数。如果要使用此方法,则需要 DLL 的 lib 文件,因为它包含链接器解析符号名称的信息。它实际上不包含代码,仅包含链接器的 DLL 上的这些信息。此外,您必须在函数声明之前使用神奇的 __declspec(dllimport) 告诉链接器您要使用的函数位于 DLL 中。这就是为什么如果您想这样做的话,您需要为 DLL 提供 .lib 和头文件(包含这些声明)。当您更改 DLL 时,您应该重建使用该 DLL 的项目,因为 .lib 文件可能已更改。
您可以在 DLL 项目和从此 DLL 导入的项目中使用相同的头文件:
MyDLL_API 被解析为 __declspec(dllexport) (在 DLL 项目中,您在项目设置中定义 MYDLL_EXPORTS)或 __declspec(dllimport )(在所有使用 dll 的项目中)。这样,您只需要 DLL 的一个头文件。
调用 DLL 函数的另一种方法是使用 LoadLibrary 和 GetProcAdress。这两个用于在运行时加载DLL。在加载时加载 DLL 和在运行时加载 DLL 之间的主要区别在于,您可以对在运行时加载 DLL 进行一些控制,而操作系统将在加载时加载 DLL 时完成这项工作(例如,如果找不到 DLL,因此不运行该进程)。
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:
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).