Маршалинг 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);
642   2  

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

    Ничего не найдено.