2010-11-10 21 views
0

J'essaie d'appeler une fonction qui alloue de la mémoire pour la chaîne, puis fait quelque chose avec la chaîne. Voici l'exemple de base qui illustre le problème:Marshalling ref IntPtr à BSTR * en C#

C++:

STDMETHODIMP CFunctionsCollection::Function2 ( 
     BSTR leftString, BSTR rightString, BSTR * conString 
    ) 
{ 
    int leftLen = lstrlen(leftString); 
    int rightLen = lstrlen(rightString); 

    *conString = new TCHAR[leftLen+rightLen+1]; 

    for (int i=0 ; i<leftLen ; ++i) 
     (*conString)[i] = leftString[i]; 
    for (int i=0 ; i<rightLen ; ++i) 
     (*conString)[leftLen+i] = rightString[i]; 
    (*conString)[leftLen+rightLen] = 0; 

    return S_OK; 
} 

L'appel suivant à partir de C++ programme fonctionne très bien:

BSTR leftString = SysAllocString(L"Left String"); 
BSTR rightString = SysAllocString(L"Right String"); 
BSTR conString; 
hr = pFunctionsCollection->Function2 (leftString, rightString, & conString); 

C# déclaration:

Int32 Function2([In, MarshalAs(UnmanagedType.BStr)] String leftString, 
       [In, MarshalAs(UnmanagedType.BStr)] String rightString, 
       [In, Out] ref IntPtr conStr); 

Appel C#:

try 
{ 
    String leftString = "Left String"; 
    String rightString = "Right String"; 
    IntPtr outStr = IntPtr.Zero; 
    pFunctionsCollection.Function2(leftString, rightString, ref outStr); 
    String outString = Marshal.PtrToStringUni(outStr); 
    Console.WriteLine("Out String = {0}", outString); 
} 
catch (Exception e) 
{ 
    Console.WriteLine("Call to Function2 failed with {0}", e.Message); 
} 

Le programme échoue avec

Appel à Function2 a échoué avec mémoire insuffisante pour continuer l'exécution du programme.

Est-ce que quelqu'un sait comment faire un tel appel de C#? ConString est un BSTR et doit être traité comme tel.

+0

C'est horrible. Pourquoi ne pas changer l'interface C# pour juste renvoyer une chaîne par référence? – sharptooth

+0

J'ai essayé mais j'ai frappé exactement la même erreur. Int32 Function2 ([In, MarshalAs (UnmanagedType.BStr)] Chaîne leftString, [In, MarshalAs (UnmanagedType.BStr)] Chaîne rightString, [In, Out] ref Chaîne conStr); String leftString = "Chaîne de gauche"; Chaîne rightString = "Chaîne droite"; Chaîne outString = Chaîne.Empty; pFunctionsCollection.Function2 (leftString, rightString, ref outString); Console.WriteLine ("Out String = {0}", outString); L'erreur était la même – Vladimir

Répondre

1

Voir http://msdn.microsoft.com/en-us/library/ms221069.aspx

  1. Vous devez utiliser SysStringLen pour obtenir la longueur des BSTRs
  2. Vous dernier paramètre en C# doit être une chaîne à marshalé comme BSTR

    [In, Out, MarshalAs (UnmanagedType. Bstr)] sur la chaîne constr

  3. Vous devez allouer la mémoire pour constr avec SysAllocString ou SysAllocStringLen

  4. Liste item

Vous ne pouvez pas allouer de la mémoire en utilisant 'new' et le convertir en BSTR. BSTR ont des exigences spécifiques pour la gestion de la mémoire et la mise en page que vous n'êtes pas satisfaisant. Vous devez toujours suivre ces conventions. L'interopération échoue car il s'attend à ce que vous suiviez les conventions pour BSTR, mais vous ne l'êtes pas.