gpt4 book ai didi

c# - 如何将带有 const char* 的 C union 映射到 C# 结构?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:41:55 26 4
gpt4 key购买 nike

在本地库的回调函数中,我需要访问一个 espeak_EVENT 数组。问题出在原C代码中的UNION语句:

typedef struct {
espeak_EVENT_TYPE type;
unsigned int unique_identifier; // message identifier (or 0 for key or character)
int text_position; // the number of characters from the start of the text
int length; // word length, in characters (for espeakEVENT_WORD)
int audio_position; // the time in mS within the generated speech output data
int sample; // sample id (internal use)
void* user_data; // pointer supplied by the calling program
union {
int number; // used for WORD and SENTENCE events. For PHONEME events this is the phoneme mnemonic.
const char *name; // used for MARK and PLAY events. UTF8 string
} id;
} espeak_EVENT;

我有

[StructLayout(LayoutKind.Explicit)]
public struct espeak_EVENT
{
[System.Runtime.InteropServices.FieldOffset(0)]
public espeak_EVENT_TYPE type;

[System.Runtime.InteropServices.FieldOffset(4)]
public uint unique_identifier; // message identifier (or 0 for key or character)

[System.Runtime.InteropServices.FieldOffset(8)]
public int text_position; // the number of characters from the start of the text

[System.Runtime.InteropServices.FieldOffset(12)]
public int length; // word length, in characters (for espeakEVENT_WORD)

[System.Runtime.InteropServices.FieldOffset(16)]
public int audio_position; // the time in mS within the generated speech output data

[System.Runtime.InteropServices.FieldOffset(20)]
public int sample; // sample id (internal use)

[System.Runtime.InteropServices.FieldOffset(24)]
public IntPtr user_data; // pointer supplied by the calling program

[System.Runtime.InteropServices.FieldOffset(32)]
public int number;

[System.Runtime.InteropServices.FieldOffset(32)]
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string name;
}

然后

public static Int32 SynthCallback(IntPtr wav, Int32 numsamples, IntPtr eventsParameter)
{
if (wav == IntPtr.Zero)
return 0;

int j=0;
while(true)
{
System.IntPtr ptr = new IntPtr(
(
eventsParameter.ToInt64()
+ (j *
System.Runtime.InteropServices.Marshal.SizeOf(typeof(cEspeak.espeak_EVENT))
)
)
);
if(ptr == IntPtr.Zero)
Console.WriteLine("NULL");

cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT));

if(events.type == cEspeak.espeak_EVENT_TYPE.espeakEVENT_SAMPLERATE)
{
Console.WriteLine("Heureka");
}
break;


//Console.WriteLine("\t\t header {0}: address={1}: offset={2}\n", j, info.dlpi_phdr, hdr.p_offset);
++j;
}


if(numsamples > 0)
{
byte[] wavbytes = new Byte[numsamples * 2];
System.Runtime.InteropServices.Marshal.Copy(wav, wavbytes, 0, numsamples*2);
bw.Write(wavbytes, 0, numsamples*2);
}
return 0;
}

但总是失败

cEspeak.espeak_EVENT events = (cEspeak.espeak_EVENT) System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(cEspeak.espeak_EVENT));

但是,当我删除

[System.Runtime.InteropServices.FieldOffset(32)][System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string name;

从 espeak_event 开始,然后就可以了。

如何在不删除 union 中的字符串的情况下完成这项工作?我需要在回调函数中访问它。

编辑:顺便说一句,如果我让它在 x64 上运行,字段偏移量会发生什么变化,以及“public IntPtr user_data;”的大小。从 32 位更改为 64 位?

嗯,想一想,fieldoffset 32​​ 是否正确?似乎我在考虑 x64 时混淆了指针大小。这很可能是另一个错误。

嗯, union int 和 char*,我猜他们从未为 x64 编译它。因为 sizof(int) 在 x64 Linux 系统上是 32 位的。

最佳答案

name 声明为 IntPtr 而不是 string 然后使用 Marshal.PtrToStringAnsi 将其转换为字符串变量。

我忽略了字符串内容是 UTF-8 的事实。如果您的文本是纯 ASCII,那很好。如果不是,则需要复制到 byte[] 数组,然后使用 Encoding.UTF8.GetString 从 UTF-8 转换。

关于c# - 如何将带有 const char* 的 C union 映射到 C# 结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6575827/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com