2010-11-17 6 views
2

je les suivantes C-tête/Exemple de code:C# Marshalling C struct et fonction


fichier d'en-tête


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


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

Exemple C Snippet


struct category_info *catinfo; 

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


Ce que je voudrais convertir en C# ...

Mon premier GUESS (et son une estimation) est:

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

Mais il ne semble pas juste ..

Toutes les suggestions .. Une fois ce qui précède est déclarée correctement en C# .. Comment devrait-il être accessible en C#

category_info catinfo; 

catmem = xyz_categories_info (sur catinfo, sur le dénombrement);

??????

Toute aide grandement appréciée.

Merci

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

Update 2

Le la mémoire allouée à xyz_categories_info est libéré en utilisant cet appel C:

void xyz_categories_info_free(void *p); 

Voici un exemple de celui-ci étant utilisé en C .... Espérons que cela explique un peu plus ..

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

Que fait exactement xyz_categories_info? En regardant son prototype, je peux deviner qu'il alloue un tableau de structures category_info et place un pointeur sur ce tableau et sa taille sur le paramètre de sortie. Que retourne-t-il? Votre extrait de code C ne contient pas cette information. –

+0

Veuillez publier un extrait de code C complet qui montre comment les informations renvoyées par cette fonction sont utilisées et validées. En utilisant des fonctions Marshal de bas niveau et le type IntPtr, nous pouvons écrire presque tout ce que C fait, bien qu'il soit vraiment beaucoup plus bête de le faire en C++/CLI. –

+0

Est-ce que ça aide Alex? – user296191

Répondre

1

Ce code a été compilé, mais pas testé. Si vous connaissez C, vous comprendrez ce qui se passe ici, c'est juste le même code C traduit en 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); 
       } 
      } 
     } 
    } 
} 
+0

Absolument PARFAIT ... !!!! Fonctionne 100% ... – user296191

+0

Merci beaucoup ... – user296191

0

Ceci est correct pour l'importation des fonctions de DLL

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

Mais pas sûr de la OUT

Votre code C de cette

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

Je bilive devrais être classe 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; 
    } 
} 

Quant à l'utiliser et en utilisant le code que je ne suis pas sûr de ce que vous essayez todo

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

Ce en C# Je ne suis pas sûr que size_t faudrait être une classe en C# mais que classe doit correspondre exactement à ce que la classe DLL est ou il y aura une incompatibilité de type c'est le problème avec le chargement cross lang DLLS

Qu'est-ce que cette DLL est censée faire? peut-être que nous pouvons aider