2010-09-07 6 views
0

J'ai des problèmes pour importer une DLL non gérée C++ dans C# [winform]. Quelqu'un peut-il aider?Problème lors de l'utilisation de C++ non géré à partir de C# à l'aide de dllimport

Fondamentalement, j'essaie simplement de créer un safearray de chaînes en C++ et en essayant de l'envoyer en C#.

Voici mon code C++.

extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY* arr) 
{ 
SAFEARRAY* myArray; 
    SAFEARRAYBOUND rgsabound[1]; 

    rgsabound[0].lLbound = 0; 
    rgsabound[0].cElements = 5; 

    myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound); 
    VARIANT* pvData = (VARIANT*)(myArray->pvData); 

    pvData[0].vt = VT_BSTR; 
    pvData[0].bstrVal = SysAllocString(L"FirstString"); 
    pvData[1].vt = VT_BSTR; 
    pvData[1].bstrVal = SysAllocString(L"SecondString"); 
    pvData[2].vt = VT_BSTR; 
    pvData[2].bstrVal = SysAllocString(L"ThirdString"); 
    pvData[3].vt = VT_BSTR; 
    pvData[3].bstrVal = SysAllocString(L"FourthString"); 
    pvData[4].vt = VT_BSTR; 
    pvData[4].bstrVal = SysAllocString(L"FifthString"); 

    arr = myArray; 
    return true; 
} 

Voici mon code C#.

[DllImport("MyData.dll", EntryPoint = "GetStringArr")] 
public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out Array strServerList); 

Je reçois une exception lorsque j'appelle GetStringArr de C#. Je suis sûr qu'il y a quelque chose de stupide que je fais. Puis-je avoir une aide s'il vous plait?

Merci d'avance.

+0

BOOL GetStringArr (SAFEARRAY * arr), je pense que cela devrait être BOOL GetStringArr (SAFEARRAY ** arr) puisque vous allouez le tableau dans la fonction. –

Répondre

0

Avez-vous accès à la source de la DLL native? Si c'est le cas, vous pouvez activer le débogage non géré dans vos options de projets gérés, et passer par le code non managé (de préférence Debug build) pour voir ce qui se passe. Si rien d'autre vous pouvez activer des exceptions dans les options du débogueur, et déboguer pour voir où l'exception native est levée.

0

Je vous recommande d'ajouter un projet C++/CLI (assembly) à votre solution C#. Cela vous permettra d'écrire du code qui vit simultanément sur les terres gérées et non gérées. Cela signifie que votre code C++/CLI peut créer un List<string^> à la place et y ajouter des chaînes managées avant de le renvoyer en C#. :-)

+0

Salut danby, je suis désolé mais je ne peux pas vraiment utiliser la liste . Merci d'avance! – Alag20

+0

OK ... pourquoi pas? --dan –

1

Plusieurs problèmes dans votre code C++. Vous renvoyez un tableau, qui nécessite que l'argument soit SAFEARRAY **. Vous bourrez également le tableau avec les données incorrectes, vous avez créé un tableau de chaînes mais vous écrivez VARIANT. Je ne sais pas quelle était l'intention, je vais garder les variantes dans le code fix:

extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY** arr) 
{ 
    SAFEARRAY* myArray; 
    SAFEARRAYBOUND rgsabound[1]; 

    rgsabound[0].lLbound = 0; 
    rgsabound[0].cElements = 5; 

    myArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound); 
    VARIANT* pvData = 0; 
    SafeArrayAccessData(myArray, (void**)&pvData); 

    pvData[0].vt = VT_BSTR; 
    pvData[0].bstrVal = SysAllocString(L"FirstString"); 
    // etc.. 
    SafeArrayUnaccessData(myArray); 

    *arr = myArray; 
    return true; 
} 

code C#:

 object[] array; 
     bool ok = GetStringArr(out array); 

    [DllImport(@"blah.dll", EntryPoint = "GetStringArr")] 
    [return: MarshalAs(UnmanagedType.U1)] 
    public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out object[] strServerList); 
+0

objet [] tableau; null bool ok = GetStringArr (tableau de sortie); 'GetStringArr (out array)' a lancé une exception de type 'System.AccessViolationException' base {System.SystemException}: {"Tentative de lecture ou d'écriture de la mémoire protégée, ce qui indique souvent qu'une autre mémoire est corrompue."} – Alag20

+0

Il y a toujours quelque chose qui ne va pas avec votre code C++. Déboguez-le, activez le débogage non géré et définissez un point d'arrêt sur votre fonction. –

+0

Mais j'ai copié tout votre code C++ comme vous le montre ci-dessus et ça ne marche toujours pas! – Alag20

1

Certains problèmes tant du côté C et .NET des choses

Du côté C

  1. Argument incorrect indirection. Puisque vous attribuez le descripteur SAFEARRAY dans la fonction, vous avez besoin d'un SAFEARRAY **.
  2. Le SAFEARRAY n'est pas correctement rempli. Vous avez créé le descripteur SAFEARRAY avec un type de base de VT_BSTR, ce qui signifie que les éléments de données doivent être des BSTR.

C Code de

extern "C" __declspec(dllexport) 
BOOL GetStringArr(SAFEARRAY** arr) 
{ 
    SAFEARRAY* myArray; 
    SAFEARRAYBOUND rgsabound[1]; 

    rgsabound[0].lLbound = 0; 
    rgsabound[0].cElements = 5; 

    myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound); 
    BSTR* pvData = (BSTR*)(myArray->pvData); 

    pvData[0] = SysAllocString(L"FirstString"); 
    pvData[1] = SysAllocString(L"SecondString"); 
    pvData[2] = SysAllocString(L"ThirdString"); 
    pvData[3] = SysAllocString(L"FourthString"); 
    pvData[4] = SysAllocString(L"FifthString"); 

    *arr = myArray; 
    return true; 
} 

Du côté .NET

  1. La convention d'appel doit être spécifié autrement, vous aurez la pile émet
  2. Vous devez définir la SafeArraySubType
  3. Vous pouvez utiliser out string[] pour obtenir le pointeur t o le SAFEARRAY

.NET code

class Program 
    { 
    static void Main(string[] args) 
    { 
     string[] data; 
     bool b = GetStringArr(out data);  
    } 

    [DllImport("MyData.dll", 
       CallingConvention = CallingConvention.Cdecl)] 
    public static extern bool GetStringArr(
     [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)] 
     out string[] strServerList);  
    } 
+0

chaîne de caractères []; bool b = GetStringArr (données de sortie); Ce qui précède a obtenu l'erreur ci-dessous. 'GetStringArr (hors données)' a lancé une exception de type de base 'System.Runtime.InteropServices.SEHException' {} System.Runtime.InteropServices.ExternalException: { "composant externe a jeté une exception"} Merci d'avance pour votre aide! – Alag20

+0

Cela signifie que quelque chose du côté C a lancé une exception (exception structurée) qui a été traduite en SEHException. Sans le code, il est difficile de deviner quelle pourrait être cette exception. J'ai le code ci-dessus dans un projet de test et peut confirmer qu'il fonctionne correctement, avez-vous quelque chose de différent? Vous devriez également fournir les informations contenues dans la SEHException, cela pourrait aider. –

+0

Pouvez-vous s'il vous plaît joindre une copie de votre code aux deux extrémités s'il vous plaît? Je viens d'utiliser le code exact sans mods dans votre code et il m'a donné cette exception. La seule différence est que j'appelle ma DLL un exe. – Alag20

Questions connexes