如何从非托管 C++ 代码获取结构化列表值到 C#?

Posted

技术标签:

【中文标题】如何从非托管 C++ 代码获取结构化列表值到 C#?【英文标题】:How to get structured list values from unmanaged c++ code to c#? 【发布时间】:2019-01-28 10:54:18 【问题描述】:

我正在用 win32 c++ 编写“ICS/VCS”文件解析器。

从文件反序列化后,我将事件数据存储在事件结构列表中。

现在我想在 c# 中访问该结构化列表。 为此,我在 DLL 中导出了函数和列表。

我不知道如何在 c# 中访问该列表。

这是我的事件结构:

struct Event 
Event(): Alarms(new list<Alarm>), RecurrenceNo(0), BaseEvent(this) 
Event(const Event &Base) :
    UID(Base.UID),
    Organizer(Base.Organizer),
    Summary(Base.Summary),
    Description(Base.Description),
    Attendee(),
    Categories(Base.Categories),
    DtStamp(Base.DtStamp),
    DtStart(Base.DtStart),
    DtEnd(Base.DtEnd),
    RRule(Base.RRule),
    Alarms(Base.Alarms),
    AttendeeCounter(Base.AttendeeCounter),
    RecurrenceNo(Base.RecurrenceNo)


    BaseEvent = Base.BaseEvent == (Event *)&Base ? (Event *)&Base : Base.BaseEvent;

~Event() 
    if (BaseEvent == this)
        delete Alarms;

operator string() const;
bool HasAlarm(const Date &From, const Date &To);

string UID, Summary, Description, Categories, Attendee[100], Organizer;
int AttendeeCounter=0;
Date DtStamp, DtStart, DtEnd;
Recurrence RRule;
list<Alarm> *Alarms;
unsigned short RecurrenceNo;
Event *BaseEvent;
;

这里是 ExportFunction.h

extern list <Event *> ListofAllEvents;
extern "C" __declspec(dllexport) list <Event *> ParseCalendar(std::string FilePath);

这是我要导出的函数 "ExportFunction.cpp"

list <Event *> ParseCalendar(std::string FilePath)

const char * InputPath = FilePath.c_str();

ICalendar Calendar(InputPath);
return ListofAllEvents;

这是 Program.cs

    [DllImport("D:\\Projects\\iCalander\\x64\\Debug\\iCalander.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr ParseCalendar(string FilePath);

它显示访问冲突错误。这是预期的,因为我没有正确访问。

我是 pInvoke 和编组的新手。

【问题讨论】:

google for ""std::string" C# interop" ...正确的答案是你不应该这样做(将 std::string 暴露给 C#)...传递普通的 (w)char* ...编辑:您也不应该公开任何标准 C++ 对象(如 std::list) 我也是这么想的。但我需要在我的 c# 应用程序中访问已解析的内容。你有更好的解决方案吗? 对于字符串参数,必须使用char*wchar_t*(或BSTR)。对于该对象,确定您可以返回一个指向 C# 的不透明指针,但是您将如何处理它呢?您可以将其想象为 C# 将 C++ 代码视为 C(指针、基类型、结构等,没有类)。考虑二进制布局。 我只使用字符串从 c# 获取文件路径。我在 C++ 应用程序内部使用 char*。这是因为 CLR 我不得不使用字符串。 @SimonMourier 你能指出我如何访问该列表的地方吗?我想在 c# 应用程序中执行 db 操作。 【参考方案1】:

如果有人想这样做,请回答我自己的问题以供将来参考。

我按照本教程进行了实验和学习互操作。

https://www.red-gate.com/simple-talk/dotnet/net-development/creating-ccli-wrapper/

https://www.red-gate.com/simple-talk/dotnet/.net-framework/5-tips-for-understanding-managed-unmanaged-interoperability-in-.net/?_ga=2.110977479.318099589.1504532675-232460203.1501855788

然后我在 c++/cli 中实现了事件结构的原型类。

public ref class iCalendarEvent 

public:
    String ^mUID;
    String ^mOrgaizer;
    String ^mSummary;
    String ^mDescription;
    String ^mCategories;
    String ^mDtStart;
    String ^mDtEnd;
    String ^mDtStamp;
    cli::array<String ^>^ mAttendee = gcnew cli::array<String ^>(100);
    int mAttendeeLength;

;

然后创建了一个 iCalendarEvent 类型的通用列表。然后,我将从 c++ 返回的每个事件对象映射到来自 c++/cli 的类 obj 中,并将其插入到 c++/CLI 的通用列表中。

【讨论】:

以上是关于如何从非托管 C++ 代码获取结构化列表值到 C#?的主要内容,如果未能解决你的问题,请参考以下文章

从非托管 c++ 调用托管 c# 函数

从非托管 c++ 调用托管 c# 函数

调试从非托管 C++ 调用的托管 .NET 代码

从非托管 C++ mfc active x dll 启动 C# 对话框

使用 COM 互操作从非托管 C++ 访问 c# 属性

将数组从非托管 C++ 传递到 C#