【问题标题】:C++/CLI, DllExport and /clr:pureC++/CLI、DllExport 和 /clr:pure
【发布时间】:2013-10-06 22:43:35
【问题描述】:

这是一个简单的原生 DLL:

Native.h

#ifdef BUILDING_NATIVE_DLL
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif

class DLLAPI Native
{
    public: void f();
};

Native.cpp

#include "Native.h"

void Native::f()
{
}

构建:

cl /DBUILDING_NATIVE_DLL /LD Native.cpp
...
    Creating library Native.lib and object Native.exp

现在我想从 C++/CLI 应用程序中使用它:

Managed.cpp

#include "Native.h"

int main()
{
    Native* native = new Native();
    native->f();
}

我可以在CLR模式“IJW”下构建它:

cl /clr Managed.cpp Native.lib
...

/out:Managed.exe
Managed.obj
Native.lib

但不是在 CLR 模式“纯”

cl /clr:pure Managed.cpp Native.lib
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01
for Microsoft (R) .NET Framework version 4.00.30319.18047
Copyright (C) Microsoft Corporation.  All rights reserved.

Managed.cpp
c:\users\...\Native.h(9) : warning C42
72: 'Native::f' : is marked __declspec(dllimport); must specify native calling c
onvention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::Native' : is marked __declspec(dllimport); must specify native cal
ling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::~Native' : is marked __declspec(dllimport); must specify native ca
lling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::Native' : is marked __declspec(dllimport); must specify native cal
ling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::operator =' : is marked __declspec(dllimport); must specify native
 calling convention when importing a function.
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Managed.exe
/clrimagetype:pure
Managed.obj
Native.lib
Managed.obj : error LNK2028: unresolved token (0A000009) "public: void __clrcall
 Native::f(void)" (?f@Native@@$$FQAMXXZ) referenced in function "int __clrcall m
ain(void)" (?main@@$$HYMHXZ)
Managed.obj : error LNK2019: unresolved external symbol "public: void __clrcall
Native::f(void)" (?f@Native@@$$FQAMXXZ) referenced in function "int __clrcall ma
in(void)" (?main@@$$HYMHXZ)
Managed.exe : fatal error LNK1120: 2 unresolved externals

因此,似乎破坏构建的是缺少原生调用约定

确实,如果我指定它:

#ifdef BUILDING_NATIVE_DLL
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif

class DLLAPI Native
{
    public: void __thiscall f();
};

这样更好:

cl /clr:pure Managed.cpp
Native.lib
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01
for Microsoft (R) .NET Framework version 4.00.30319.18047
Copyright (C) Microsoft Corporation.  All rights reserved.

Managed.cpp
c:\users\...\Native.h(10) : warning C4
272: 'Native::Native' : is marked __declspec(dllimport); must specify native cal
ling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::~Native' : is marked __declspec(dllimport); must specify native ca
lling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::Native' : is marked __declspec(dllimport); must specify native cal
ling convention when importing a function.
c:\users\...\Native.h(10) : warning C4
272: 'Native::operator =' : is marked __declspec(dllimport); must specify native
 calling convention when importing a function.
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Managed.exe
/clrimagetype:pure
Managed.obj
Native.lib

但仍然对生成的成员发出警告。

以下是问题:

  • 是否可以为整个类指定调用约定,生成的成员将从该类继承?
  • 如果头文件没有指定调用约定,如果不能修改,如何在CLR模式“纯”下构建?

谢谢。

【问题讨论】:

    标签: .net dll c++-cli dllexport


    【解决方案1】:

    尝试将本机头文件的#include 括起来

    #pragma managed(push, off)
    #include "Native.h"
    #pragma managed(pop)
    

    显然/clr:pure 编译单元不能有非托管的定义函数,但这些只是导入的声明——它应该可以工作。

    但总体而言,不建议导出整个类。导出工厂函数并将其用于类构造,然后返回指向接口(具有纯虚拟成员的基类)的指针并将其用于成员访问,会更安全。这就是 COM 所做的,并且该技术在语言和编译器版本之间非常兼容。

    【讨论】:

    • 谢谢 Ben,很好的尝试,但是 #pragmas 并没有改变任何东西。工厂的好处,我也喜欢 COM 方法,虽然我不一定使用它。
    猜你喜欢
    • 2012-08-09
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多