【问题标题】:C++ __declspec( dllexport ) functions cannot access instance variablesC++ __declspec(dllexport) 函数无法访问实例变量
【发布时间】:2012-03-01 10:15:49
【问题描述】:

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

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

Test 是在使用包含 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 函数公开到消费者使用的第二组标头中。

【问题讨论】:

    标签: c++ dllexport declspec


    【解决方案1】:

    当您在“消费代码”中将Test 按值从一个位置传递到另一个位置时,您将导致slicing 发生,因为客户端代码不知道该变量并为该类计算了不正确的大小Test.

    要解决这个问题,你也应该在客户端代码中声明变量,或者你可以提供某种静态工厂函数,只允许客户端代码传递指向Tests 的指针以避免切片.

    【讨论】:

    • 谢谢我更新了这个问题,因为我意识到混合中也有继承。我试过 __declspec(dllexport) Foo* var;但我得到“__declspec 修饰符对此声明无效”
    • @PaulRidgway 啊,抱歉我错了,只需将Foo* var 也添加到客户的Base 中(或者如果sizeof(void*) == sizeof(Foo*),您甚至可以使用void* var
    【解决方案2】:

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

    1. 提供创建类实例的 createTest 静态函数(工厂方法)。这里最好的做法是提供一个纯接口(无实例变量)。

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

    【讨论】:

      【解决方案3】:

      有什么理由不使用:

      #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();
      }
      

      【讨论】:

      • 有很多我想隐藏的原始类方法,所以无法导出和导入整个东西。我想导出一个方法子集,这些方法又调用其他内部和外部方法,一些公共的和受保护的 - 可以在 DLL 内访问,但不能在外部访问。
      猜你喜欢
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2023-01-26
      • 1970-01-01
      • 2021-09-22
      • 2015-02-24
      • 1970-01-01
      相关资源
      最近更新 更多