如何写一个托管和非托管下都能编译成功的C++结构体,方便在不同环境下调用?
不懂C++,请各位高手指点一下。需求是需要封装一个动态库,方便C#调用C++对应结构体,该结构体也应用于静态库,代码如下:```//A.h#ifdefDOTNET#def...
不懂C++,请各位高手指点一下。
需求是需要封装一个动态库,方便C#调用C++对应结构体,该结构体也应用于静态库,代码如下:
```
//A.h
#ifdef DOTNET
#define TEST_STRUCT(name) [StructLayoutAttribute(LayoutKind::Sequential, Pack = 1)]\
typedef public ref struct name
#else
#define TEST_STRUCT(name) typedef struct name
#endif
```
```
TEST_STRUCT(A)
{
unsigned char Count;
B* DataList;
A()
{
Count = 0;
DataList = NULL;
}
~A()
{
if (DataList != NULL)
{
delete [] DataList;
DataList = NULL;
}
}
bool copy(char* input, unsigned long count, char* pMem, unsigned long ulMemCount)
{
DataList = new B[Count];
memcpy(DataList, &input[6], Count*8);
return true;
}
}A
```
我创建了一个C++ 动态库工程
代码如下:
```
// TestCLI.h
#include "..\A.h"
#ifndef DOTNET
#define DOTNET;
#endif
#pragma once
```
然后在工程内引入A.h
编译时,
```
B* DataList;
```
会报错。
应该如何改造呢? 展开
需求是需要封装一个动态库,方便C#调用C++对应结构体,该结构体也应用于静态库,代码如下:
```
//A.h
#ifdef DOTNET
#define TEST_STRUCT(name) [StructLayoutAttribute(LayoutKind::Sequential, Pack = 1)]\
typedef public ref struct name
#else
#define TEST_STRUCT(name) typedef struct name
#endif
```
```
TEST_STRUCT(A)
{
unsigned char Count;
B* DataList;
A()
{
Count = 0;
DataList = NULL;
}
~A()
{
if (DataList != NULL)
{
delete [] DataList;
DataList = NULL;
}
}
bool copy(char* input, unsigned long count, char* pMem, unsigned long ulMemCount)
{
DataList = new B[Count];
memcpy(DataList, &input[6], Count*8);
return true;
}
}A
```
我创建了一个C++ 动态库工程
代码如下:
```
// TestCLI.h
#include "..\A.h"
#ifndef DOTNET
#define DOTNET;
#endif
#pragma once
```
然后在工程内引入A.h
编译时,
```
B* DataList;
```
会报错。
应该如何改造呢? 展开
1个回答
展开全部
托管与非托管混合编程部分
这部分是最重要,也是最难的。VisualStudio环境提供了一些头文件来帮助开发者链接这些关键词。
#include <vcclr.h>
但是,并非就到这儿就结束了。我们还需要小心涉及的一些陷阱,尤其是是CLR(托管代码)和native(非托管代码)一些关键词之间数据的传递。
以下是个类的头文件输出一个托管的部分
#pragma once
#ifdef NATIVEDLL_EXPORTS
#define NATIVEDLL_API __declspec(dllexport)
#else
#define NATIVEDLL_API __declspec(dllimport)
#endif
#include <string>
using namespace std;
#ifdef _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
class NATIVEDLL_API CPerson
{
public:
// Initialization
CPerson(LPCTSTR pszName, const SYSTEMTIME* birthDate);
virtual ~CPerson();
// Accessors
unsigned int get_Age() const;
tstring get_BirthDateStr() const;
SYSTEMTIME get_BirthDate() const;
private:
// Embedded wrapper of an instance of a CLR class
// Goal: completely hide CLR to pure unmanaged C/C++ code
void* m_pPersonClr;
};
强调一点,尽量在头文件里保证只有非托管代码,混合编程在cpp中去实现,数据的传递。比如: 应该尽量避免使用vcclr.h中的函数, 进行混合编程。这就是为什么定义一个void指针来包装CLR对象。
这部分是最重要,也是最难的。VisualStudio环境提供了一些头文件来帮助开发者链接这些关键词。
#include <vcclr.h>
但是,并非就到这儿就结束了。我们还需要小心涉及的一些陷阱,尤其是是CLR(托管代码)和native(非托管代码)一些关键词之间数据的传递。
以下是个类的头文件输出一个托管的部分
#pragma once
#ifdef NATIVEDLL_EXPORTS
#define NATIVEDLL_API __declspec(dllexport)
#else
#define NATIVEDLL_API __declspec(dllimport)
#endif
#include <string>
using namespace std;
#ifdef _UNICODE
typedef wstring tstring;
#else
typedef string tstring;
#endif
class NATIVEDLL_API CPerson
{
public:
// Initialization
CPerson(LPCTSTR pszName, const SYSTEMTIME* birthDate);
virtual ~CPerson();
// Accessors
unsigned int get_Age() const;
tstring get_BirthDateStr() const;
SYSTEMTIME get_BirthDate() const;
private:
// Embedded wrapper of an instance of a CLR class
// Goal: completely hide CLR to pure unmanaged C/C++ code
void* m_pPersonClr;
};
强调一点,尽量在头文件里保证只有非托管代码,混合编程在cpp中去实现,数据的传递。比如: 应该尽量避免使用vcclr.h中的函数, 进行混合编程。这就是为什么定义一个void指针来包装CLR对象。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询