Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.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#_C#_Unity3d_Emulation_Libretro - Fatal编程技术网

无法将结构数组从c编组到c#

无法将结构数组从c编组到c#,c#,unity3d,emulation,libretro,C#,Unity3d,Emulation,Libretro,我试图将一个c结构数组封送到c#(使用Unity)中,但是,无论我使用什么方法,我总是会遇到异常或崩溃 我正在加载符合(或应该…)libretro API的dll(libretro内核),c/c++端对我不可用(更准确地说,我不允许修改),这意味着我必须处理从该dll返回的数据,无论其布局如何 C API结构定义如下(RETRO_NUM_CORE_OPTION_VALUES_MAX是一个值为128的常量): struct retro\u core\u选项\u值 { 常量字符*值; 常量字符*标签

我试图将一个c结构数组封送到c#(使用Unity)中,但是,无论我使用什么方法,我总是会遇到异常或崩溃

我正在加载符合(或应该…)libretro API的dll(libretro内核),c/c++端对我不可用(更准确地说,我不允许修改),这意味着我必须处理从该dll返回的数据,无论其布局如何

C API结构定义如下(RETRO_NUM_CORE_OPTION_VALUES_MAX是一个值为128的常量):

struct retro\u core\u选项\u值
{
常量字符*值;
常量字符*标签;
};
结构恢复\u核心\u选项\u定义
{
常量字符*键;
常量字符*desc;
常量字符*信息;
结构恢复核心选项值[恢复数量恢复核心选项值恢复最大值];
常量字符*默认值;
};
结构还原\u核心\u选项\u内部
{
结构追溯(核心)选项(定义)美国;;
结构还原\u核心\u选项\u定义*本地;
};
目前,我的C#映射如下所示:

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
公共结构恢复核心选项值
{
公共字符*值;
公共字符*标签;
}
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi)]
公共结构恢复\u核心\u选项\u定义
{
公共字符*密钥;
公共字符*desc;
公共字符*信息;
[Marshallas(UnmanagedType.ByValArray,SizeConst=RETRO\u NUM\u CORE\u OPTION\u VALUES\u MAX)]
公共追溯核心期权价值[]价值;
公共字符*默认值;
}
[StructLayout(LayoutKind.Sequential)]
公共结构修复\u核心\u选项\u内部
{
公共INTR us;
公共IntPtr本地;
}
回调函数在C#端具有以下签名:

公共不安全bool回调(retro_环境cmd,void*数据)
retro_环境是一个转换为枚举的无符号整数,在其上执行一个开关,然后指示如何适当地处理void*数据指针。这里的数据是一个追溯的核心选项

我可以通过两种方式进行void*转换:

retro\u core\u options\u intl intl=Marshal.PtrToStructure((IntPtr)数据);

retro\u core\u options\u intl*intl=(retro\u core\u options\u intl*)数据;
我使用这两种方法(第一种方法是intl.us,第二种方法是intl->us)得到一个可读地址,在我的特定情况下,“local”部分是空的,但API将“us”部分定义为必需的。intl->us指向一个长度可变的retro\u core\u option\u定义数组

我遇到的问题是试图读取这个强制构造中的值

我现在尝试加载的数组可以在这里看到:在第51行

API为“struct retro_core_option_value[retro_NUM_core_option_values_MAX]”结构成员定义了一个固定大小,但传入的代码几乎总是定义为一个数组,其中最后一个元素是“{NULL,NULL}”,以指示结束,因此它们并不总是(几乎从不)包含128个值

我试过:

retro\u core\u options\u intl intl=Marshal.PtrToStructure((IntPtr)数据);
retro\u core\u option\u definition us=Marshal.PtrToStructure(intl.us);
这将产生一个NullReferenceException

retro\u core\u options\u intl intl=Marshal.PtrToStructure((IntPtr)数据);
追溯核心选项定义[]us=Marshal.PtrToStructure(intl.us);
这将提供一个长度为0的retro_core_option_定义数组

retro\u core\u options\u intl intl=Marshal.PtrToStructure((IntPtr)数据);
retro_core_option_definition us=新的retro_core_option_definition();
元帅组织(国际美国、美国);
这会给出一个“目的地是装箱的值”

这就是我的基本立场。。。 任何帮助都将不胜感激:)


整个代码库都可以在这里找到:

我看到的第一件事是,在
C
代码中,您要么需要使用
wchar\u t
类型,而不是
char
类型,要么可以使用
byte
而不是
char
System.Char是两个字节char为1字节


您还可以在C#code中使用
System.String
,并使用
MarshalAs
属性对其进行注释,告诉它输入的是什么类型的字符数据,例如Ansi或Unicode C字符串。

我看到的第一件事是,您需要在
C
代码中使用
wchar\t
类型,而不是
char
类型,或者您可以在C#中使用
byte
而不是
char
System.Char是两个字节char为1字节


您还可以在C#code中使用
System.String
,并使用
MarshalAs
属性对其进行注释,告诉它输入的是什么类型的字符数据,例如Ansi或Unicode C字符串。

不知道这是否有用,但我偶然发现了一个关于C和C#与字符类型的区别的问题:哦,兄弟。整合Unity插件太难了,我会放弃回家:这是iOS还是什么平台?程序本身已经能够在windows、linux、macos、android和iOS上运行基本功能(也就是加载一些内核并正确启动一些游戏)。一些更麻烦的功能只在windows上运行,一个只在windows上运行,同时强制使用opengl后端。虽然它不是完美的,但大多数的斗争都得到了某种程度的解决。但这个问题真的让我难堪,我尝试了很多解决方案。。。我开始把数据发送到C++并在那里读它(这似乎是可行的),但是如果有可能的话,我宁愿有一个C的解决方案。不知道这是否会有帮助,但是我偶然发现了这一点,它和C语言的C语言和C语言的区别:哦兄弟。整合Unity插件太难了,我会放弃回家:这是用于iOS还是什么平台?程序本身已经能够在windows、linux、macos等平台上运行基本功能