C# 从PInvoke返回结构

C# 从PInvoke返回结构,c#,c++,pinvoke,C#,C++,Pinvoke,我试图从C++调用一个结构到C++ dll,并且我得到一些我不理解的复杂和坏的行为。如果我的结构包含一个构造函数,那么当返回它时,如果它小于12字节,我就会得到一个内存访问冲突。如果它更大,就没有问题。如果我删除构造函数,它适用于所有大小。我想这可能与我的呼叫是c风格有关,但我找不到相关信息。因此,如果有人能解释或指出正在发生的事情,我将不胜感激。下面是一些代码示例,这些代码可以工作,也可以不工作: 有效的代码 C++侧标题: #define DLL_API __declspec(dllexpo

我试图从C++调用一个结构到C++ dll,并且我得到一些我不理解的复杂和坏的行为。如果我的结构包含一个构造函数,那么当返回它时,如果它小于12字节,我就会得到一个内存访问冲突。如果它更大,就没有问题。如果我删除构造函数,它适用于所有大小。我想这可能与我的呼叫是c风格有关,但我找不到相关信息。因此,如果有人能解释或指出正在发生的事情,我将不胜感激。下面是一些代码示例,这些代码可以工作,也可以不工作:

有效的代码

C++侧标题:

#define DLL_API __declspec(dllexport)

struct Struct4Byte
{
 int x1;
};

struct Struct12Byte
{
 int x1;
 int x2;
 int x3;
 Struct12Byte() { x1 = 0; x2 = 1; x3 = 2; }
};

#ifdef __cplusplus
extern "C" {
#endif
 DLL_API Struct4Byte Function4Byte(int x);
 DLL_API Struct12Byte Function12Byte(int x);
#ifdef __cplusplus
}
#endif
C++文件:

Struct4Byte Function4Byte(int x)
{
 Struct4Byte output;
 output.x1 = 1 + x;
 return output;
}

Struct12Byte Function12Byte(int x)
{
 Struct12Byte output;
 output.x1 = 1 + x;
 output.x2 = 2 + x;
 output.x3 = 3 + x;
 return output;
}
在呼叫端(C#),我会:

不起作用的代码

如果我现在将头文件中Struct4Byte的定义更改为:

struct Struct4Byte
{
 int x1;
 Struct4Byte(){ x1 = 0; }
};
然后我得到内存访问冲突

我注意到了一些可能感兴趣的事情。调用Function4Byte时问题已经存在。在函数中放置一个制动点并查看x(我在下面再次放置该函数)表明x得到一些随机值

Struct4Byte Function4Byte(int x)
{
 Struct4Byte output;
 output.x1 = 1 + x;
 return output;
} 

我可能发现了这个问题。他们的警告是我没有注意到的:警告C4190:“Function4Byte”指定了C链接,但返回与C不兼容的UDT“Struct4Byte”。从本次讨论中可以清楚地看出,这可能会导致一些未定义的行为,并且结构的布局可能会更改:


这似乎可以解释我遇到的问题。

是的,这样返回结构是不受支持的,Microsoft的主线p/Invoke文章都没有这样返回结构的例子。反正我也没读过

下面是一个git hub示例,说明您的项目是如何以正确的方式进行的

我发现这篇文章对结构和类的封送最有帮助
呼叫约定
应该是
Cdecl
也许?至于填充,x64将填充到8字节,这似乎没有任何效果。但我不是100%确定怎么做。在C++中使用了<代码> [StuttFaySoal[LoopOut.Services,Posie= 8)] /Cuth>,我还尝试了C++中的<代码>奇怪的是,对于一个有两个int成员(8个字节)的结构,我也有同样的问题,但对于12个字节或更大的成员,我却没有。我想我可以通过不包含任何构造函数或添加一些额外数据来解决这个问题。但是,我真的不知道问题是否解决了,或者它是否只是碰巧工作在一起。不返回结构,而是将对结构的引用作为参数传递,怎么样?这显然是一种选择,也是我为我返回的大部分数据所做的。但我主要关心的不是让它工作,而是理解为什么它不工作。否则,当我以其他方式返回结构时,这很可能也是一个问题。
Struct4Byte Function4Byte(int x)
{
 Struct4Byte output;
 output.x1 = 1 + x;
 return output;
}