C++ 从DLL导入函数时出现错误LNK2019
我正在学习如何构建一个DLL并从另一个项目中调用它(我还希望DLL不仅可以被C/C++调用,还可以被Python调用)。以下是我构建DLL的代码: callbacktesetDLL.h:C++ 从DLL导入函数时出现错误LNK2019,c++,dll,C++,Dll,我正在学习如何构建一个DLL并从另一个项目中调用它(我还希望DLL不仅可以被C/C++调用,还可以被Python调用)。以下是我构建DLL的代码: callbacktesetDLL.h: #ifdef CALLBACKTESTDLL_EXPORTS #define CALLBACKTESTDLL_API __declspec(dllexport) #else #define CALLBACKTESTDLL_API __declspec(dllimport) #endif typedef
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
callbacktestDLL.cpp:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
通过上面的代码,我得到了callbacktestDLL.dll
和callbacktestDLL.lib
。使用dependens,可以显示DLL中函数的名称:
现在我想从另一个项目调用DLL中的函数:
CallDLL.h:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
然而,当我运行该项目时,它告诉我:
错误LNK2019:未解析的外部符号\uuuu imp\uu strott
和错误LNK2019:未解析的外部符号\uuu imp\uu NumCompare
。我已经在CallDLL项目的根文件夹下复制了.lib
和.dll
文件。为什么会发生这种情况?我怎样才能解决它?谢谢你的关注。我终于来了。详情如下:
生成DLL的文件包括:
callbacktestDLL.h:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
callbacktestDLL.cpp:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
CallDLL.cpp:
#ifdef CALLBACKTESTDLL_EXPORTS
#define CALLBACKTESTDLL_API __declspec(dllexport)
#else
#define CALLBACKTESTDLL_API __declspec(dllimport)
#endif
typedef int(CALLBACK *p)(char*);
CALLBACKTESTDLL_API int __stdcall StrToInt(char*);
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
CALLBACKTESTDLL_API int __stdcall StrToInt(char* StrInput)
{
int IntResult;
IntResult = atoi(StrInput);
return IntResult;
}
CALLBACKTESTDLL_API char* __stdcall NumCompare(p FuncP, char* StrInput, int b)
{
int a = FuncP(StrInput);
if (a>b)
{
return "a is bigger than b";
}
else
{
return "b is bigger than a";
}
}
LIBRARY
EXPORTS
StrToInt @1
NumCompare @2
#pragma comment(lib,"callbacktestDLL.lib")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(*p)(char*);
extern "C" _declspec(dllimport) int StrToInt(char* InpuString);
extern "C" _declspec(dllimport) char* NumCompare(p FuncP, char*, int b);
#include "stdafx.h"
int main()
{
p FuncP_R = StrToInt;
NumCompare(FuncP_R, "1234", 40);
return 0;
}
typedef int(CALLBACK *p)(char*);
extern "C" __declspec(dllexport) int __stdcall StrToInt(char* InputString);
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b);
#include "stdafx.h"
#include <stdio.h>
#include "callbacktestDLL.h"
#include <stdlib.h>
extern "C" CALLBACKTESTDLL_API int __stdcall StrToInt(char* InputString)
{
int IntResult;
IntResult = atoi(InputString);
return IntResult;
}
extern "C" __declspec(dllexport) char* __stdcall NumCompare(p FuncP, char* InputString, int b)
{
int a = FuncP(InputString);
if (a>b)
{
return "a is bigger than b\n";
}
else
{
return "b is bigger than a\n";
}
}
#pragma comment(lib,"callbacktestDLL")
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
typedef int(__stdcall *p)(char*); //same as typedef int(CALLBACK *p)(char*) in callbacktestDLL.h
extern "C" _declspec(dllimport) int __stdcall StrToInt(char* InputString); //exactly same as what's in callbacktestDLL.h apart from dllimport
extern "C" _declspec(dllimport) char* __stdcall NumCompare(p FuncP, char* InputString, int b); //exactly same as what's in callbacktestDLL.h apart from dllimport
#include "stdafx.h"
int main()
{
p FuncP_R;
char* a = "1234";
FuncP_R = StrToInt;
printf(NumCompare(FuncP_R, a, 42));
return 0;
}
它像预期的那样工作。我认为我犯的一个错误是导入时缺少
\uu stdcall
。也许这个名字也有错误。我将继续测试它。您应该始终包含相同的头文件以定义一致的接口。创建不同的头文件容易出错。对接口的下一次更改可能会使接口不兼容
实现函数的模块与使用函数的模块之间存在细微差异。区别在于\u declspec(dllimport)
或\u declspec(dllexport)
。这就是为什么头文件包含
# ifdef CALLBACKTESTDLL_EXPORTS
实现这些函数的模块也会导出这些函数。因此,必须在项目设置中定义符号。如果在命令行编译,则必须将/D CALLBACKTESTDLL\u EXPORT
添加到编译器参数中
顺便说一句:如果您定义了
CALLBACKTESTDLL\u EXPORT
宏CALLBACKTESTDLL\u API
包含\u declspec(dllexport)
。这将导致链接器创建DLL导出表。.DEF
不是必需的。您应该删除它,因为。。。。。它再次定义了接口(在不同的级别)。是否与库链接?并且DLL应该与可执行文件位于同一目录中。您是否为DLL定义了CALLBACKTESTDLL\u EXPORTS
?(顺便说一句,您只需要在函数声明之前设置导出声明。)extern“C”
防止名称损坏,而库仍然导出损坏的名称。该.def文件没有用处,因为它没有列出正确(损坏)的名称。在客户端代码中不使用.h文件是一个非常糟糕的主意。重新键入函数名时,您忘记了u stdcall属性。这将更改修饰的函数名。不要这样做,请使用#在客户端代码中也包括“callbacktestDLL.h”
。不太明显这是怎么回事,如果有必要,请仔细检查您没有在客户端项目中定义CALLBACKTESTDLL导出。该.h文件不是秘密,需要正确使用DLL。用于构建DLL的其他文件(如.cpp文件)与客户端程序员无关。因此,在极不可能的情况下,有人这样做,一定要扔掉DLL。如果你不这样做,那么你就有可能侵犯版权,这可能是相当昂贵的。这种方法可能会给你一个DLL,你可以使用。但它也有一些退步。有关详细信息,请参阅我的答案。谢谢您告诉我这些详细信息。您能告诉我什么时候使用.DEF
?另一个问题,在我自己的回答中,虽然CallDLL.h
中的函数名称与中的函数名称不同,但为什么我仍然可以导入它们?