Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中封送布尔数组与封送单个布尔(定义为int)到布尔#_C#_Marshalling - Fatal编程技术网

C# 在C中封送布尔数组与封送单个布尔(定义为int)到布尔#

C# 在C中封送布尔数组与封送单个布尔(定义为int)到布尔#,c#,marshalling,C#,Marshalling,在C API中,BOOL的定义如下 #ifndef BOOL #define BOOL int 我有一个结构,其中包括一个简单的BOOL成员和一个BOOL数组 struct SomeStruct { BOOL bIsSomething; BOOL bHasSomething[5]; } 现在我发现,当我想要转换整个结构时,我必须以不同的方式封送它们: 单个BOOLI使用I1进行封送,固定长度数组必须使用I4进行封送(如果我不这样做,它们的结构大小将不匹配,并且我将

在C API中,BOOL的定义如下

#ifndef BOOL
#define BOOL int
我有一个结构,其中包括一个简单的BOOL成员和一个BOOL数组

struct SomeStruct
{
    BOOL    bIsSomething;
    BOOL    bHasSomething[5];
}
现在我发现,当我想要转换整个结构时,我必须以不同的方式封送它们:

单个
BOOL
I使用
I1
进行封送,固定长度数组必须使用
I4
进行封送(如果我不这样做,它们的结构大小将不匹配,并且我将无法将这些结构的数组提取到C中):

我怀疑我做错了什么,因为我不知道为什么我需要对同一类型进行不同的封送处理,这取决于我是将其作为固定大小的数组还是作为单个成员。 如果我将它们都编组为
I4
我会得到一个
系统.ArgumentException

An unhandled exception of type 'System.ArgumentException' occurred in SomeDll.dll    
Additional information: Type 'Namespace.Document+SomeNativeStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

bool
是一种很难进行互操作的类型。布尔值有许多互不兼容的定义,因此
bool
被认为是不可删除的类型-也就是说,它需要真正编组,而不仅仅是在数据上粘贴“完全是bool”标记。而不可空袭类型的数组则更加棘手

最简单的解决方案是避免完全使用
bool
。只需将
bool[]
替换为
int[]
,如果原始类型实际上是32位int(取决于编译器和平台),您将获得正确的互操作。然后,您可以手动将互操作结构复制到布局更合理的托管结构(如果您选择的话)——这也让您能够完全控制解释哪些int值分别对应于true和false

一般来说,本机互操作总是很棘手;您需要很好地理解实际内存布局以及所处理的值和类型的含义。这些类型是不够的——它们太模糊了,尤其是在标准C中(即使在今天,这也是本机互操作的标准)。标题是不够的——您还需要文档,甚至可能需要在(本机)调试器中查看一下


额外的危险来自这样一个事实,即没有安全网告诉您您正在做一些错误的事情-错误的互操作方法可能会在几年内表现良好,然后突然在您脸上爆炸,例如,
true
值恰好是
42
,而不是更常见的
-1
,而您的位运算会发生微妙的中断(如果您使用不安全的代码,这种情况实际上可能发生在C#中)。对于小于32768的值,一切都可能运行良好,然后崩溃得可怕。有很多难以捕捉的错误案例,因此您需要格外小心。

我认为您的问题在于c#中的布尔大小。您是否尝试更改C++结构来匹配C API(使用int代替BoL)?所以他们是I4(不是我)。因此,将c#结构设为int而不是布尔更简单。然后消除上面不需要的bIsSimething类型。从bHasSomething中删除阵列子类型。为什么要将一个布尔封送为
I1
,另一个封送为
I4
?听起来你只是在用锤子敲打互操作,直到它看起来能工作为止。非托管结构的大小是多少?在任何情况下,请使用
int[]
而不是
bool[]
。布尔值不可blittable,所以您确实不想在byval互操作数组中使用它们。@Luaan这就是我在最后一段中提到的。我也不明白为什么我应该将一个封送为
I1
,另一个封送为
I4
,但正是这一点使它起了作用。我想了解为什么我不能将
I4
用于阵列的单个bool-like。但是我想我可以在本机结构中使用
int[]
,然后在C#中将其转换为
bool[]
?(是的,它完全是在用锤子敲打互操作-我不是说我想这样使用它:))哦,我现在明白了-你说当你不将第一个BOOL封送为I1时会发生异常,对吗?您正在调用的DLL是64位DLL吗?您是否尝试附加本机调试器以检查结构的实际内存布局?还要注意,
int
不一定是32位整数——例如,根据编译器和平台的不同,它也可以很容易地成为16位整数。对齐也将取决于编译器,因此请确保对其进行验证(或者根据规范,或者至少根据调试器中看到的实际布局)。什么是对的,什么是错的?0而不是-0?
An unhandled exception of type 'System.ArgumentException' occurred in SomeDll.dll    
Additional information: Type 'Namespace.Document+SomeNativeStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.