从c头中提取:
struct ArgvArgcResult {
char* buffer;
char** argv;
uint argc;
};
bool get_argv_and_argc_of_pid(pid_t pid, struct ArgvArgcResult* result);
值得注意的是,c“字符串”不能依赖任何特定的编码,因此可能无法将它们表示为 C# 字符串,我认为
byte[]
是正确的,但我不确定如何指示长度不是在编译时已知。
Trying to express the c struct in C# 我不知所措使用什么类型的
char*
和char**
:
[StructLayout(LayoutKind.Sequential)]
public struct ArgvArgcResult {
public char* buffer;
public char** argv;
public ulong argc;
}
此外,当从 c# 为 dllimport 调用 c fn 时,指向结构的指针是什么样的?
[DllImport("libgetargv.dylib", CallingConvention = CallingConvention.Cdecl)] static extern bool get_argv_and_argc_of_pid(nuint pid, struct ArgvArgcResult* result);
char
在 C/C++ 中是 8 位的,所以你需要 byte
。您可以将其作为 byte[]
数组传递,但 char*
也可以作为 ANSI 字符串传递。您似乎在进行自己的内存管理,因此您可以将argv
作为指向指针的指针传递。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ArgvArgcResult
{
public string buffer;
public nint argv;
public ulong argc;
}
将结构传递为
ref
[DllImport("libgetargv.dylib", CallingConvention = CallingConvention.Cdecl)]
static extern bool get_argv_and_argc_of_pid(
nuint pid,
ref ArgvArgcResult result);
并且当你使用它时,你可以像这样阅读
argv
for (var i = 0; i < result.argc; i++)
{
var ptr = Marshal.ReadIntPtr(argv, IntPtr.Size * i);
var str = Marshal.PtrToStringAnsi(ptr);
// do stuff
}
// don't forget to free memory
如果实际上 C 函数使用
buffer
作为它自己的缓冲区,那么你必须传入一个内存指针
[StructLayout(LayoutKind.Sequential)]
public struct ArgvArgcResult
{
public nint buffer;
public nint argv;
public ulong argc;
}
var result = new ArgvArgcResult();
try
{
result.buffer = Marshal.AllocHGlobal(someSizeHere);
// fill buffer??
// call function, handle strings
}
finally
{
Marshal.FreeHGlobal(result.buffer);
}