Маршалинг C# для структуры и функции C
У меня есть следующий пример заголовка/кода 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#...
Мое первое предположение (и это предположение):
[StructLayout(LayoutKind.Sequential)]
public struct category_info
{
int id;
[MarshalAs(UnmanagedType.LPStr)]
StringBuilder name;
[MarshalAs(UnmanagedType.LPStr)]
StringBuilder description;
};
[DllImport ("mydll.dll", CharSet = кодировка.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr xyz_categories_info ([Out]category_info cat, [Out]int catSize);
Но это просто что-то тут не так..
Любые предложения.. Как только все вышесказанное будет правильно объявлено в C#.. Как он должен быть доступен в C#
category_info catinfo;
Catmem = xyz_categories_info (out catinfo, out catcount);
??????
Любая помощь очень ценится.
Спасибо
================================================================================
Обновление 2
Память, выделенная в xyz_categories_info, освобождается с помощью этого C вызов:
void xyz_categories_info_free(void *p);
Ниже приведен пример его использования в с.... Надеюсь, это объясняет это немного больше..
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);
2 ответов:
Этот код компилируется, но не тестируется. Если вы знаете 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);Но не уверен насчет выхода
Ваш C-код этого
struct category_info { int id; const char *name; const char *description; };I 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, или будет несоответствие типов это проблема с загрузкой cross lang DLL
Что эта DLL должна делать? может быть, мы сможем помочь
Comments