C 结构体和函数的 C# 编组

发布于 2024-10-02 12:53:49 字数 1945 浏览 4 评论 0原文

我有以下 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 = CharSet. Ansi,CallingConvention = CallingConvention.Cdecl)]
公共静态 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

使用此 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);

I have the following C Header/Code Example:


Header file


struct category_info {
 int id;
 const char *name;
 const char *description;
};


DLLEXPORT
void* xyz_categories_info(struct category_info **info, size_t *info_count);

Example C Snippet


struct category_info *catinfo;

size_t catcount;
size_t i;
int max_name_len = 0;
void *catmem = xyz_categories_info(&catinfo, &catcount)


Which I would like to convert to c#...

My First GUESS (and its a guess) is:

[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)]
public static extern IntPtr xyz_categories_info([Out]category_info cat, [Out]int catSize);

But it just doesn't look right..

Any suggestions.. Once the above is declared correctly in C#.. How should it be accessed in C#

category_info catinfo;

catmem = xyz_categories_info(out catinfo, out catcount);

??????

Any help greatly appreciated.

Thanks

================================================================================

Update 2

The memory allocated in xyz_categories_info is freed using this C call:

void xyz_categories_info_free(void *p);

Below is an example of it being used in C.... Hope this explains it a bit more..

    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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

玻璃人 2024-10-09 12:53:49

此代码已编译,但未经测试。如果您了解 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);
                }
            }
        }
    }
}

This code is compiled, but not tested. If you know C, you will understand what happens here, this is just the same C code translated to 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);
                }
            }
        }
    }
}
郁金香雨 2024-10-09 12:53:49

这对于导入 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;
};

应该是 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 类完全匹配,否则会出现类型不匹配,这是加载跨语言 DLL 的问题

。该 DLL 应该做什么?也许我们可以帮忙

This is correct for importing DLL's functions

    [DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr xyz_categories_info([Out]category_info cat, [Out]int catSize);

But not sure about the OUT

Your C code of that

struct category_info {
 int id;
 const char *name;
 const char *description;
};

I bilive should be C# Class

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;
    }
}

As to using it and using the code i'm not sure what your trying todo

size_t catcount;
size_t i;
int max_name_len = 0;
void *catmem = xyz_categories_info(&catinfo, &catcount)

This in C# I'm not sure about as size_t would have to be an class in C# but then that class has to match exactly what the DLL class is or there will be a type mismatch this is the problem with loading cross lang DLLS

What is that DLL supposed to be doing? maybe we can help

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文