在Windows项目中我们定义一个接口类
class Interface {
public:
virtual ~Interface() { }
virtual void func() = 0;
};
Run Code Online (Sandbox Code Playgroud)
和一个工厂函数
__declspec(dllexport) Interface *construct();
Run Code Online (Sandbox Code Playgroud)
在 DLL 内。Interface当然,DLL 内部有具体的专门化,但我们不导出它。不过我们可以在 DLL 之外使用它。这是如何运作的?vftable由 构造的实例由construct()指向 DLL 未导出的函数的函数指针组成。这种方法可以接受还是或多或少是一种黑客行为?
我无法将 DLL 隐式链接到 C 控制台应用程序。我使用 Visual Studio 2008。
我创建了空的 DLL 项目“Library”,其中仅包含一个文件 main.c:
__declspec(dllexport) int get_value()
{
return 123;
}
Run Code Online (Sandbox Code Playgroud)
我还使用文件 main.c 创建了空控制台项目“CallingProgram”:
__declspec(dllimport) int get_value();
void main()
{
int result = get_value();
}
Run Code Online (Sandbox Code Playgroud)
我将“Library.lib”添加到“Linker\Input\Additional Dependency”中。
我仍然有这个错误:
error LNK2019: unresolved external symbol __imp__get_value referenced in function _main
Run Code Online (Sandbox Code Playgroud)
我测试了使用 LoadLibrary/GetProcAddress 创建的 DLL - 它工作正常。
我使用 DumpBin 检查了 Library.dll,它看起来也不错:
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file library.dll
File Type: DLL
Section contains the following …Run Code Online (Sandbox Code Playgroud) 我有一个特定的用例,其中可执行文件需要导出某些符号,这些符号由可执行文件在运行时加载的动态加载的 DLL 导入和使用。
可执行文件与一些静态库链接,这些静态库实际上具有导出的符号,而 DLL 使用这些静态库标头导入这些符号。
如果这些符号在可执行文件中未使用或未引用,则链接器将删除它们,因此它们不会被导出,因此在加载时不可用于 DLL。
我分别使用 --whole-archive 和 -force_load 选项在 GCC / clang 上解决了这个问题。
Windows 上的 MSVC 怎么样?我使用 __declspec(dllexport) 和 __declspec(dllimport) 在 Windows 上导出和导入符号。
编辑:有关代码参考,您可以在此处找到代码: https: //github.com/hunkabhicupid/exeexport
这个问题与这些帖子1、2类似,但这些帖子的答案并没有帮助我找到解决方案,或者我发现它们没有用。
Run Code Online (Sandbox Code Playgroud)__declspec(dllexport) int __stdcall TestFunktion(void) { return 0; }
在 Visual Studio 中是否有任何简单的方法可以创建没有修饰且没有 DEF 文件的函数?
让我们假设我们有一个DLL,并且应该有一个全局存储在其中的数组将被导出,我们想要通过从文件中读取一些内容来初始化它,所以我个人发现自己别无他法它在一个结构中能够使用构造函数初始化:
struct Construction{
public:
Construction(){
//do the initialization thing and read the needed data from the file
}
SomeType sTArray[100];
};
__declspec(dllexport) Construction obj();
Run Code Online (Sandbox Code Playgroud)
现在它将被使用,程序员可以初始化对它的引用,然后使用如下的引用:
SomeType (&arrayRef)[100]=obj.sTArray;
Run Code Online (Sandbox Code Playgroud)
现在你觉得我在任何情况下都错了吗?
我正在尝试在Mac OS X 10.6上编译一个简单的DLL,并且对于声明DLL为全世界提供使用的函数的正确方法感到困惑.以下来自可靠来源的示例代码,我提出:
__declspsec(dllexport) pascal int ReturnTheNumberFive(void)
Run Code Online (Sandbox Code Playgroud)
但gcc barfs就可以了.示例代码实际上是MACPASCAL和DLLExport,我假设是宏.我浏览了#defines的示例代码,SDK等,并插入了我发现的内容.这些定义可能已经埋没在#ifs中,所以我发现并不好.不合逻辑地,如果我只是做明显的并使用DLLExport和MACPASCAL,编译器也会barfs,所以这不是解决方案.
使应用程序可以使用DLL函数的正确方法是什么?
我在VS中创建了新的Win32项目,并为此目的选择了动态库(*.dll).
我在主文件中定义了一些导出函数:
__declspec(dllexport)
int TestCall(void)
{
int value = 4 / 2;
std::cout << typeid(value).name() << std::endl;
return value;
}
__declspec(dllexport)
void SwapMe(int *first, int *second)
{
int tmp = *first;
*first = *second;
*second = tmp;
}
Run Code Online (Sandbox Code Playgroud)
当我看到dumpin/exports时,我得到了:
ordinal hint RVA name
1 0 00001010 ?SwapMe@@YAXPEAH0@Z
2 1 00001270 ?TestCall@@YAHXZ
Run Code Online (Sandbox Code Playgroud)
我正在调用C#这样的版本:
[DllImport(@"lib1.dll", EntryPoint = "?TestCall@@YAHXZ",
CallingConvention = CallingConvention.Cdecl)]
static extern int TestCall();
Run Code Online (Sandbox Code Playgroud)
这不是使用导出方法的正确形式.我在C++ DLL项目中为导出方法生成这样的名称失败了吗?
我正在写一个将导出函数和类的DLL.但是现在我有一个关于导出函数的问题.
如果我的函数签名如下:
__declspec(dllexport) int fn1(FILE *theFile);
Run Code Online (Sandbox Code Playgroud)
我应该包含所以定义FILE吗?这里的最佳做法是什么?如果我想导出一个接受或返回自定义类型的函数,那么这些类型的头文件是否也应包含在导出的头文件中?
我从C++ DLL导出了一个方法,然后从VB.net表单应用程序中调用它.C++方法当前没有返回值(void)但我想改进它并返回一个表示一系列错误代码的int.(如果一切顺利,我计划返回零.)
定义这些错误代码的最佳位置在哪里以及如何?
我应该在CPP文件的顶部执行以下操作:
#define ERR_NEGATIVE_CELL_SIZE 1
#define ERR_INVALID_FILE_PATH 2
etc
Run Code Online (Sandbox Code Playgroud)
VB.net应用程序还将定义这些相同的代码,然后根据代码向用户显示UI消息.
显然我宁愿在DLL中抛出异常并在VB.net中捕获它(以及相关的异常消息),但这似乎不可能使用extern"C"__declspec(dllexport)方法.
很高兴听到其他设计模式.我还计划通过C++控制台可执行文件公开DLL方法,因此将错误消息一次存储在DLL中并将它们提供给控制台和UI应用程序是理想的选择.
我使用 C# DLL 导出(UnmanagedExports - https://www.nuget.org/packages/UnmanagementExports)使我的托管 C# DLL 可被非托管代码(如 Delphi)访问。我的问题是只有第一个函数参数从 delphi 传输到 C# dll:
C# DLL 部分
[DllExport("SomeCall", CallingConvention.StdCall)]
public static String SomeCall([MarshalAs(UnmanagedType.LPWStr)] String data1, [MarshalAs(UnmanagedType.LPWStr)] String data2)
{
//Data1 is never filled with some string data.
String result = WorkWithData(data1);
//Data2 is filled with some string data.
result += WorkWithData(data2)
return result;
}
Run Code Online (Sandbox Code Playgroud)
Delphi部分(调用部分):
SomeCall: function(data1: PWideChar; data2: PWideChar;): String StdCall;
procedure DoSomeDLLWork(data1: PWideChar; data2: PWideChar);
var
dllCallResult: String;
begin
dllCallResult := SomeCall(data1,data2);
end
Run Code Online (Sandbox Code Playgroud)
本例的问题是只填充了data2。data1 永远不会被填充。我已经尝试过 StdCall 和 …
我已经按照 MSDN 文档完成了所有操作,但我的函数仍然没有导出。 链接1 链接2 链接3
这是我所拥有的(2 个项目,DLL 和从 dll 导入的应用程序),如下所示(简短版本):
DLL函数.h
#prgma once
#ifdef COMPILE_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif // COMPILE_DLL
namespace wsl
{
EXPORT bool PointInTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y);
}
Run Code Online (Sandbox Code Playgroud)
DLL函数.cpp
#include "functions.h"
namespace wsl
{
bool PointInTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{
// implementation...
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
DLL dllmain.cpp …
是否可以导出包装类的结构而不包装它(结构仅包含枚举和基元)?假设我的包装如下所示:
WorkerWrapper.h
#ifdef TESTEXPORTDLL_EXPORTS
#define TESTEXPORTDLL_API __declspec(dllexport)
#else
#define TESTEXPORTDLL_API __declspec(dllimport)
#endif
class Worker;
struct JobTypeInfo;
template class TESTEXPORTDLL_API std::unique_ptr<Worker>;
class TESTEXPORTDLL_API WorkerWrapper {
private:
std::unique_ptr<Worker> fWorker;
public:
WorkerWrapper();
~WorkerWrapper();
WorkerWrapper(WorkerWrapper&& aThat);
WorkerWrapper& operator= (WorkerWrapper&& aThat);
void DoJob(JobTypeInfo aTypeInfo);
};
Run Code Online (Sandbox Code Playgroud)
这是通过使用WorkerWrapper.cpp定期实现的处理,这不是我问题的原因。该类是前向声明的,并包含一个我想要导出的结构。unique_ptrstd::moveWorkerWorkerWrapper
工人.h
struct JobTypeInfo
{
typedef enum
{
DoThis,
DoThat,
DoNothing
} CalcType;
CalcType sCalcType;
//... primitives
};
class Worker
{
public:
void DoJob(JobTypeInfo aTypeInfo);
};
Run Code Online (Sandbox Code Playgroud)
我在这里能做什么?
提前致谢。
我正在处理一个遗留的 DLL,它有很多东西是从 DOS C 代码开始的,当时还没有布尔值的概念。但 DLL 仍在积极开发中并且仍在不断发展。许多旧的导出方法具有如下签名:
_declspec(dllexport) int IsConditionTrue();
Run Code Online (Sandbox Code Playgroud)
从名称来看,该函数应该返回TRUE/FALSE值,但由于它被声明为int,程序员必须假设 API 可以返回任何内容。我正在对 DLL 进行一轮更改,并且想知道更改这些声明是否安全,BOOL以代替澄清预期的 API 用法:
_declspec(dllexport) BOOL IsConditionTrue();
Run Code Online (Sandbox Code Playgroud)
BOOL被声明为typedef int BOOL;,所以我认为编译器或导出函数的已编译使用者应该没有区别,对吧?我只是不想对十几个导出函数进行更改,然后花一周的时间寻找并重新编译消耗导出版本的损坏的可执行文件int。