2009-08-25 6 views
1

Encore une autre de mes questions P/Invoke! J'ai cette fonction C:Passant struct par référence provoquant AccessViolationException

int _ei_x_new(ei_x_buff* x); 

Essentiellement, il initialise une nouvelle structure de tampon. En C#, j'ai ceci:

[DllImport(EIDLL, EntryPoint = "_ei_x_new")] 
public static extern int ei_x_new(out ei_x_buff x); 

ei_x_buff est assez simple:

typedef struct ei_x_buff_TAG { 
    char* buff; 
    int buffsz; 
    int index; 
} ei_x_buff; 

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct ei_x_buff { 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    public string buff; 
    public int buffsz; 
    public int index; 
} 

Mais quand je fais ceci:

ei_x_buff buffer; 
Ei.ei_x_new(out buffer); 

Je reçois un AccessViolationException:

Att vidé pour lire ou écrire de la mémoire protégée. C'est souvent une indication que l'autre mémoire est corrompue.

Ai-je besoin d'allouer de la mémoire ou quelque chose? C'est un morceau de code tellement simple que je ne vois pas de problèmes flagrants.

EDIT: code natif pour _ei_x_new:

// In my wrapper library 
DLL_EXPORT int _ei_x_new(ei_x_buff* x) { 
    return ei_x_new(x); 
} 

// In external library being wrapped 
int ei_x_extra = 100; 

int ei_x_new(ei_x_buff* x) 
{ 
    x->buff = malloc(ei_x_extra); 
    x->buffsz = ei_x_extra; 
    x->index = 0; 
    return x->buff != NULL ? 0 : -1; 
} 

Répondre

0

Couple de choses

  • Utilisez à ne pas ref dans la signature PInvoke que vous voulez que les données mobilisées dans les deux sens (dans et hors de la fonction native)
  • Pouvez-vous publier la signature native comme leur pourrait être un problème avec la définition. En particulier, le membre de buff

EDIT

Juste pour éliminer une possibilité, passer l'élément buff être tapé IntPtr sans attributs. Si cela ne provoque pas un crash, il s'agit probablement d'un problème de triage avec le type de chaîne.

+0

La signature P/Invoke est déjà utilisée. Si vous vouliez dire "ref not out", cela donne le même résultat. La signature native est donnée dans la question: int _ei_x_new (ei_x_buff * x); –

+0

Oh, vous voulez dire la signature native de la structure?J'ai édité ma question pour le montrer. –

+0

La modification à IntPtr a arrêté l'exception. Puis-je le laisser comme ça, ou dois-je utiliser un autre type? –

0

Avez-yo marquons le tampon comme épinglé dans la mémoire en utilisant l'instruction fixed:

exemple:

// assume class Point { public int x, y; } 
// pt is a managed variable, subject to garbage collection. 
Point pt = new Point(); 
// Using fixed allows the address of pt members to be 
// taken, and "pins" pt so it isn't relocated. 
fixed (int* p = &pt.x) 
{ 
    *p = 1; 
} 
+0

Ne devrait pas être pertinent dans ce scénario – JaredPar

0

Je pense que cela fonctionnera avec la chaîne aussi, si vous venez initialisze le tampon correctement sur la Côté C Gardez à l'esprit que les retours du tampon malloc peuvent contenir des ordures, donc vous devriez ajouter quelque chose comme

si (x-> buff) x-> buff [0] = '\ 0';

Une autre chose que vous pouvez vouloir vérifier est que vous utilisez la même convention d'appel du côté natif et géré. Le CLR suppose _stdcall sauf si vous spécifiez autre chose dans l'attribut DllImport.

Questions connexes