[英]C# Marshalling for C Struct and Function
我有以下C标头/代码示例:
头文件
struct category_info {
int id;
const char *name;
const char *description;
};
DLLEXPORT
void* xyz_categories_info(struct category_info **info, size_t *info_count);
示例C代码段
struct category_info *catinfo;
size_t catcount;
size_t i;
int max_name_len = 0;
void *catmem = xyz_categories_info(&catinfo, &catcount)
我想将其转换为C#...
我的第一个GUESS(及其猜测)是:
[StructLayout(LayoutKind.Sequential)]
public struct category_info
{
int id;
[MarshalAs(UnmanagedType.LPStr)]
StringBuilder name;
[MarshalAs(UnmanagedType.LPStr)]
StringBuilder description;
};
[DllImport(“ mydll.dll”,CharSet = CharSet.Ansi,CallingConvention = CallingConvention.Cdecl)]
公共静态外部IntPtr xyz_categories_info([Out] category_info cat,[Out] int catSize);
但这看起来并不正确。
任何建议。.一旦在C#中正确声明了以上内容。.应该如何在C#中对其进行访问
category_info catinfo;
catmem = xyz_categories_info(退出catinfo,退出catcount);
??????
任何帮助,不胜感激。
谢谢
================================================== ==============================
使用以下C调用释放xyz_categories_info中分配的内存:
void xyz_categories_info_free(void *p);
下面是在C语言中使用它的一个示例。希望这能对它有所解释。
category_buffer = xyz_categories_info(&category_info, &category_count);
if( !category_buffer )
{
// Failed Log a message and exit.
exit(1);
}
for(j=0; j<category_count; j++)
{
if( category_info[j].id == 0 )
continue;
printf("id: %d name: '%s' description: '%s'\n",
category_info[j].id,
category_info[j].name,
category_info[j].description
);
}
xyz_categories_info_free(category_buffer);
此代码已编译,但未经测试。 如果您了解C,您将了解这里发生的事情,这与转换为C#的C代码相同。
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApplication1 { public struct category_info { public int id; public IntPtr name; public IntPtr description; }; class Program { [DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr xyz_categories_info(ref IntPtr cat, ref int catSize); [DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void xyz_categories_info_free(IntPtr cat); static void Main(string[] args) { IntPtr categories = IntPtr.Zero; IntPtr category_buffer = IntPtr.Zero; int category_count = 0; category_info info = new category_info(); IntPtr current; try { category_buffer = xyz_categories_info(ref categories, ref category_count); if (category_buffer == IntPtr.Zero) { return; } if (category_count == 0) { return; } for (int j = 0; j < category_count; j++) { if (IntPtr.Size == 4) { current = new IntPtr(categories.ToInt32() + j * Marshal.SizeOf(info)); } else { current = new IntPtr(categories.ToInt64() + j * Marshal.SizeOf(info)); } info = (category_info)Marshal.PtrToStructure(current, typeof(category_info)); if (info.id == 0) { continue; } Console.WriteLine(info.id); Console.WriteLine(Marshal.PtrToStringAnsi(info.name)); Console.WriteLine(Marshal.PtrToStringAnsi(info.description)); } } finally { if (category_buffer != IntPtr.Zero) { xyz_categories_info_free(category_buffer); } } } } }
这对于导入DLL的功能是正确的
[DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr xyz_categories_info([Out]category_info cat, [Out]int catSize);
但不确定OUT
你的C代码
struct category_info {
int id;
const char *name;
const char *description;
};
我bilive应该是C#类
public class category_info
{
public const string name {get; set};
public const string description {get; set};
public int id {get; set;}
public category_info(int id, const string name, const string description){
this.name = name;
this.description = description;
this.id = id;
}
}
至于使用它和使用代码,我不确定您要做什么
size_t catcount;
size_t i;
int max_name_len = 0;
void *catmem = xyz_categories_info(&catinfo, &catcount)
在C#中,我不确定,因为size_t必须是C#中的一个类,但是该类必须与DLL类完全匹配,否则类型将不匹配,这是加载跨语言DLLS的问题
该DLL应该在做什么? 也许我们可以帮忙
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.