我有一个DLL,其中包含一个静态成员的类.我用__declspec(dllexport)
它来使用这个类的方法.但是当我将它链接到另一个项目并尝试编译它时,我得到静态数据的"未解析的外部符号"错误.
例如,在DLL中,Test.h
class __declspec(dllexport) Test{
protected:
static int d;
public:
static void m(){int x = a;}
}
Run Code Online (Sandbox Code Playgroud)
在DLL中,Test.cpp
#include "Test.h"
int Test::d;
Run Code Online (Sandbox Code Playgroud)
在使用Test的应用程序中,我调用m().
我也尝试分别为每个方法使用__declspec(dllexport),但我仍然得到静态成员的相同链接错误.
如果我使用dumpbin检查DLL(.lib),我可以看到符号已导出.
例如,应用程序在链接时给出以下错误:
1>Main.obj : error LNK2001: unresolved external symbol "protected: static int CalcEngine::i_MatrixRow" (?i_MatrixRow@CalcEngine@@1HA)
Run Code Online (Sandbox Code Playgroud)
但是.lib的dumpbin包含:
Version : 0
Machine : 14C (x86)
TimeDateStamp: 4BA3611A Fri Mar 19 17:03:46 2010
SizeOfData : 0000002C
DLL name : CalcEngine.dll
Symbol name : ?i_MatrixRow@CalcEngine@@1HA (protected: static int CalcEngine::i_MatrixRow)
Type : data
Name type : …
Run Code Online (Sandbox Code Playgroud) 在VS C/C++中你可以使用extern "C" __declspec(dllexport) -function declaration-
.
如何在C#dll中完成此操作?C#代码是否与上面的代码相同?
编辑:更多信息
我正在尝试为Notepad ++创建一个插件,我想使用C#,但到目前为止我看到的常见方法是使用传统的C++代码和上面的调用来导出Notepad ++期望导入的一些函数和呼叫.有一个使用C#的示例应用程序,但这仍然需要一个加载器DLL,我从下面的评论/答案中假设是C#的唯一方法.
我正在将基于ATL的静态库转换为DLL,并且在使用ATL CString
类(在atlstr.h中找到)的任何导出类上收到以下警告:
警告C4251:'Foo :: str_':类'ATL :: CStringT'需要让dll接口被'Foo'类的客户端使用
我正确地声明Foo
该类是通过导出的__declspec(dllexport)
.这是一个我可以放心忽视的警告,还是我做错了什么?DLL项目设置被设置为与ATL动态链接,但这似乎没有任何区别.
例如:
#ifdef DLLTEST_EXPORTS
#define DLLTEST_API __declspec(dllexport)
#else
#define DLLTEST_API __declspec(dllimport)
#endif
// This class is exported from the DLLTest.dll
class DLLTEST_API Foo
{
public:
Foo();
CString str_; // WARNING C4251 HERE
};
Run Code Online (Sandbox Code Playgroud)
此DLL的所有客户端也将使用ATL.
foo.cpp(33918) : fatal error C1854: cannot overwrite information formed
during creation of the precompiled header in object file: 'c:\somepath\foo.obj'
Run Code Online (Sandbox Code Playgroud)
咨询MSDN关于这一点给了我以下信息:
在为同一文件指定/ Yc(创建预编译头)选项后,指定了/ Yu(使用预编译头)选项.某些声明(例如声明包括__declspec dllexport)使其无效.
在这种情况下,我们使用dllexport和预编译头文件.有没有人遇到过这个并且知道任何解决方法?非常感谢任何有关这个问题的信息.
谢谢
我可以在DLL中放一个类吗?我写的课是这样的:
class SDLConsole
{
public:
SDLConsole();
~SDLConsole(){};
void getInfo(int,int);
void initConsole(char*, char*, SDL_Surface*, int, int, int);
void sendMsg(char*,int, SDL_Surface*);
void cls(SDL_Surface*);
private:
TTF_Font *font;
SDL_Surface *consoleImg;
int width, pos, height, line, size, ctLine;
SDL_Surface* render(char*,int);
};
Run Code Online (Sandbox Code Playgroud)
我知道如何加载DLL并在DLL中使用该函数,但是如何在DLL中放置一个类?非常感谢你.
我想基于dll导出的类定义派生类.基类在项目A中定义,派生类在项目B中定义.
首先,在项目A中,定义了预处理器MYDLL_BUILD.我使用头文件来指定导出/导入:
#if !defined(MYDLL_BUILD)
# pragma comment(lib, "myDll.lib")
#endif
#if defined(MYDLL_BUILD)
# define MYDLL_API __declspec(dllexport)
#else
# define MYDLL_API __declspec(dllimport)
#endif
Run Code Online (Sandbox Code Playgroud)
然后我定义基类:
class MYDLL_API DllObject
{
public:
virtual ~DllObject() {}
protected:
DllObject() { m_count = 3; }
private:
int m_count;
};
Run Code Online (Sandbox Code Playgroud)
在项目B中,未定义预处理器MYDLL_BUILD.这是派生类:
class MyClass : public DllObject
{
public:
~MyClass(){}
MyClass() { m_data = 20; }
private:
int m_data;
};
Run Code Online (Sandbox Code Playgroud)
我已经包含了dll和lib文件,但仍然得到了未解析的外部符号错误:
2>Test_Entry.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall ADAI::DllObject::~DllObject(void)" (__imp_??1DllObject@ADAI@@UAE@XZ) referenced in function "public: virtual __thiscall …
Run Code Online (Sandbox Code Playgroud) 我试图导出一个简单的测试函数,用于处理一个应用程序(fyi:mIRC),它将调用约定指定为:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Run Code Online (Sandbox Code Playgroud)
现在,要从应用程序中调用它,我将使用test_func,但我注意到由于名称错误,它并不像我想象的那么简单.
通过类似的主题,我已经了解到将extern"C"与__declspec(dllexport)结合使用是一种等效的(某种程度上)方法,可以将重整数据删除到模块定义(.def).但是,当使用extern/dllexport方法时,我的函数(作为示例)始终是_test_func @ numbers,而.def删除了所有需要导出到的应用程序所需的修改.
有人可以解释一下这是为什么吗?我只是对这两种方法感到好奇.谢谢!
我有一个本机(非托管)C++应用程序(使用wxWidgets来实现它的价值).我正在考虑用C#编写一个单独的工具应用程序,其中包含基于winform的对话框.将一些对话框放在一个单独的DLL中会很有用,因为我希望能够在我的C++应用程序中使用它们.
但是我不知道要实现这个目标需要多少麻烦,这是否特别容易?
编辑:
我不需要直接调用对话框函数.我只需要一种方法让我的C++应用程序调用C#DLL中的API来传递数据,以及C#DLL在C++应用程序中调用某种观察者/后退对象上的方法的方法.
例如来自C++:
CSharpManager *pCSM = SomehowGetPointerToCSharpObject();
CSharpObserver pCSO = new CSharpObserver;
pCSM->RegisterCPlusPlusObserver(pCSO);
pCSM->LaunchDialog();
Run Code Online (Sandbox Code Playgroud)
当用户在C#对话框中执行操作时,将调用pCSO方法将数据传递回C++
因此,我认为这几乎是一个原始的C++/C#通信问题.但是虽然我知道C++和C#但我不知道.net本身是如何工作的.我知道COM,但我真的宁愿避免它,我怀疑我工作的任何其他开发人员都知道它.
我已经设置了一个库,提供了一个从标准异常派生的异常类:
#include <stdexcept>
#include <string>
class BaseException : public std::runtime_error
{
public:
BaseException( std::string const & msg );
};
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.在Unix上编译和处理得很好.现在我准备将其编译成Windows DLL:
#ifdef WIN32
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT
#endif
#include <stdexcept>
#include <string>
class MY_EXPORT BaseException : public std::runtime_error
{
public:
BaseException( std::string const & msg );
};
Run Code Online (Sandbox Code Playgroud)
但是,这给了我警告C4275 : non – DLL-interface class 'std::runtime_error' used as base for DLL-interface class 'BaseException'
.
不幸的是,我对微软风格的文档有些过敏:过于冗长,而且不是很重要.它让我完全不知道对我解决问题的实际期望是什么.
你们有人可以开导我吗?我可以删除基类,但然后捕获std::runtime_error
或std::exception
不会捕获我的自定义异常类,我非常希望这是可能的.所以...?
有没有办法在教程中只将函数导出到DLL cos,它们总是使用类似的东西导出类:
static __declspec(dllexport) double Add(double a, double b);
Run Code Online (Sandbox Code Playgroud)
在一个类中,上面的语句不会导致任何问题,但是没有它给出的类:
dllexport/dllimport requires external linkage
Run Code Online (Sandbox Code Playgroud)