2

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);
2
  • What does xyz_categories_info exactly? Looking at its prototype, I can guess that it allocates array of category_info structures and places pointer to this array and its size to output parameter. What does it return? Your C code snippet doesn't contain this information. Commented Nov 17, 2010 at 12:03
  • Please post full C code snippet which shows how information returned by this function is used and released. Using low-level Marshal functions and IntPtr type, we can write almost everything, that C does, though it is really much beter to do this in C++/CLI. Commented Nov 17, 2010 at 12:45

2 Answers 2

1

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);
                }
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.