2010-03-05 5 views
4

Le problème ci-dessous est ralated à ma précédente questionFonction C++ appelant à partir de l'application C#. Tentative de lecture ou d'écriture mémoire protégée

Converting static link library to dynamic dll

Ma première étape a consisté à développer une dll, cela a été fait. (Merci John Knoeller Prakash. Votre entrée a été très utile)

Maintenant, quand j'appelle la fonction dans la dll de mon application C# je reçois l'erreur

« Tentative de lecture ou d'écriture de mémoire protégée. Cela est souvent une indication que l'autre mémoire est corrompue. "

Voici le C++ définition

extern "C" DEMO2_API void Decompress(char* inp_buff, unsigned short* 
inp_len, char* buffer_decomp,unsigned *output_len,unsigned short* errorCode); 

Mon C# converstion p/Involke

private static extern void Decompress(
     byte[] inp_buff, 
     ref ushort inp_len, 
     byte[] buffer_decomp, 
     ref int output_len, 
     ref ushort errorCode 
     );   

Et je l'appelle comme ci-dessous

byte[] dst = new byte[2048]; 
    int outlen = 2048; 
    ushort errorCode = 0; 
    Decompress(src, (ushort)src.Length, dst, ref outlen,ref errorCode); 
    return dst; 

Quel est le problème?

Répondre

0

Le 4ème paramètre doit être passé en utilisant le mode out au lieu de ref. Cela a résolu le problème.

0

Je vois une incompatibilité de signature sur le paramètre inp_len. Dans la définition C++, vous utilisez un pointeur vers un entier non signé court, tandis que dans la méthode C# vous utilisez un ushort.

+0

Je l'ai édité. – Manjoor

0

pour les pointeurs vous devez utiliser le type de IntPtr

0

@necrostaz

Il ne faut pas que nous utilisons IntPtr pour les pointeurs.

Regardez ci-dessous toutes ces quatre déclarations sont valables et actuellement je l'utilise.

[DllImport("user32.dll")] 
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, String lParam); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, StringBuilder lParam); 

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, String lParam); 

question reste ouverte

0

Outre les disparus « ref » sur la déclaration inp_len que Maurits a, vous devez vous assurer que votre pointeur tailles correspondance.

Si vous utilisez un 32 bits du système d'exploitation, vous devriez être OK, mais si votre code fonctionne trop 64 bits, vous devez vous assurer que ce soit:

  • vous marquez votre. assembly net entry en tant que x86 (pas de CPU)
  • ou
  • Vous fournissez une version 32 bits et 64 bits de la DLL C++ et installez la version correcte pour l'interopérabilité d'appel.
+0

Je comprends. Mais je cours Win Xp Professional 32 bits et j'ai essayé avec IntPtr. Toujours obtenir la même erreur .. – Manjoor

+0

Juste pour être sûr, avez-vous changé la signature pour lire "ref ushort inp_len"? – marklam

0

J'ai eu le même problème il y a deux ans. Dans mon cas, la raison de la violation d'accès était que la mémoire était allouée en dehors de la DLL. En tant que solution, j'ai ajouté deux fonctions pour l'allocation de mémoire et la désallocation à la DLL.

Une autre solution pourrait être une modification des paramètres de sécurité .net. Certains mots clés sont "Outil de police de sécurité d'accès au code" (caspol.exe) et "Outil de configuration .NET Framework" (mscorcfg.msc). Dans VS, il existe également un onglet de sécurité dans la boîte de dialogue des propriétés du projet. Je ne suis pas un expert en.sécurité nette afin que quelqu'un d'autre devrait savoir plus de détails.

+0

Intéressant .. Je ne veux pas faire face à la sécurité .Net. Pouvez-vous s'il vous plaît fournir votre solution pour la même chose. – Manjoor

+0

Voici deux liens qui peuvent vous aider: http://ask.metafilter.com/79680/Calling-unmanaged-DLL-functions-from-C et http://social.msdn.microsoft.com/Forums/en- US/csharplanguage/thread/6e843243-baf4-4eb1-8a20-c691ad47762c – user287715

+0

@alexj, il semble être la raison derrière cela. Mais malheureusement, je ne pouvais pas comprendre ce qu'ils font et comment puis-je l'implémenter dans ma propre fonction. J'appreaciate si vous s'il vous plaît décrire un peu. Merci.. – Manjoor

0

Le code suivant s'exécute sans problème. Il est très semblable à la vôtre:

C++:

extern "C" __declspec(dllexport) void TestFunction(char* inp_buff, 
       unsigned short* inp_len, 
       char* buffer_decomp, 
       unsigned *output_len, 
       unsigned short* errorCode) 
{ 
    //copy input buffer to output buffer 
    int size = min(*inp_len,*output_len); 
    for(int i=0; i<size; i++) 
     buffer_decomp[i] = inp_buff[i]; 

    errorCode = 0; 
} 

C#:

using System; 
using System.Runtime.InteropServices; 

class Program 
{ 
    [DllImport("TEST.DLL")] 
    public static extern void TestFunction(byte[] inp_buff, 
              ref ushort inp_len, 
              byte[] out_buff, 
              ref int out_len, 
              ref ushort errorCode); 

    static void Main(string[] args) 
    { 
     //prepare input buffer 
     byte[] inp_buff = new byte[20]; 
     inp_buff[0] = (byte)'T'; 
     inp_buff[1] = (byte)'E'; 
     inp_buff[2] = (byte)'S'; 
     inp_buff[3] = (byte)'T'; 
     ushort inp_len = (ushort)inp_buff.Length; 

     //prepare output buffer 
     byte[] out_buff = new byte[20]; 
     int out_len = out_buff.Length; 

     ushort errorCode = 0; 
     TestFunction(inp_buff, ref inp_len, out_buff, ref out_len, ref errorCode); 

     //see if copying was successful 
     for(int i=0; i<out_len; i++) 
      Console.Out.Write(out_buff[i]); 
    } 
} 

essayer. J'ai jeté un coup d'oeil sur les parties ouvertes de la bibliothèque que vous utilisez. Voici un extrait direct de la fonction lzo_decomp:

in = lzo_malloc(IN_LEN); 
     out = lzo_malloc(OUT_LEN); 
    wrkmem = lzo_malloc(LZO1Z_999_MEM_COMPRESS); 
    if (in == NULL || out == NULL || wrkmem == NULL)  
    { 

    printf("out of memory\n"); 

    } 


    in_len = IN_LEN; 
    lzo_memset(in,0,in_len); 
    lzo_memset (out, 0, OUT_LEN); 


    memcpy (out, &input_buffer, inp_buff_len); 

lzo_free(wrkmem); 
lzo_free(out); 
lzo_free(in); 


r = lzo1z_decompress(out,*inp_len,in,&out_len,NULL); 

Pour la sérénité: « in » et « out » ne sont pas les arguments de la fonction pour les tampons d'entrée et de sortie, mais pointeurs temporaires. Que pouvez-vous voir (à côté de mauvais code formaté)? Les deux seuls buffers lzo1z_decompress sont appelés avec "in" et "out". Et ces deux tampons sont libérés avant l'appel. Je ne suis pas surpris qu'il y ait une violation d'accès. Je ne peux que souligner le conseil de nobugz: Contacter l'auteur.

Questions connexes