C ++ __declspec(dllexport)函数无法访问实例变量

时间:2012-02-08 22:25:03

标签: c++ dllexport declspec

我试图通过导出为DLL(在Windows / VS 2010上)来保护某些C ++代码。

在下面的示例中,var在超类构造函数中设置,调试器显示它肯定设置为引用某事

测试是在代码中构造的,该代码使用了Test类包含在其中的DLL。

但是当从测试实例调用go时(从DLL调用,但DLL消费者调用调用方法)var是空指针(它的值为0)

这是一种简化,因为我不允许分享实际的代码。

//Headers

class Base {
  public:
    __declspec(dllexport) Base();      
  private:
    Foo* var;
};

class Test : Base {
public:
  __declspec(dllexport) Test();
  __declspec(dllexport) void go();
private:
};

//Body

Base::Base() {
  var = new Foo();
}

Test::Test() : Base() {
}

void Test::go() {
  var->do_something();
}

在消费代码中,标题是

class Base {
public:
  __declspec(dllimport) Base();
}; 

class Test {
public:
  __declspec(dllimport) Test();
  __declspec(dllimport) void go();
};

实际代码要复杂得多,但如果有人能告诉我dllexport是否存在对实例变量的已知限制,或者我是否更有可能在空指针上调用方法,我将不胜感激。测试,或者它可能是一个dllexport和继承问题。这个代码在我拆分使用者代码和DLL代码在同一个项目之前有效,它只是在拆分后才破坏,dllexporting / dllimporting函数我想暴露给消费者使用的第二组头文件。

3 个答案:

答案 0 :(得分:1)

当您在“使用代码”中将值Test从一个地方传递到另一个地方时,您将导致slicing发生,因为客户端代码不知道该变量并计算错误班级Test的大小。

要解决此问题,您还应该在客户端代码中声明变量,或者您可以提供某种静态工厂函数,并且只允许客户端代码将指针传递给Test。避免切片。

答案 1 :(得分:0)

如果从提供给客户的代码中删除实例变量,则只有您自己的代码知道对象的实际大小并可以创建它。从头脑中你可以通过两种方式解决这个问题:

  1. 提供createTest静态函数,用于创建类的实例(工厂方法)。这里最好的事情是提供一个纯接口(没有实例变量)。

  2. 如果您只想隐藏课程的特定部分,可以使用pimpl习语(wikipedia article)。

答案 2 :(得分:0)

有没有理由不使用:

#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif

class fooEXPORT exportClass
{
public:
  void function( void );
  Foo * var;
}

如果您想要隐藏您的课程(或您班级的一部分),您可以将其用作私人会员:

#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif

class classToHide;

class fooEXPORT exportClass
{
public:
  void function( void );
  classToHide * var;
}

在Cpp:

#include "exportClass.h"
#include "classToHide.h"

void exportClass::function( void )
{
  var->function();
}