2016-04-03 4 views
0

Stuck in sehr naiven Problem. Ich habe zwei Projekte, eins in C++ und andere in C#. Idee ist, C++ - Projekt als Wrapper um einige C-Bibliotheken zu verwenden. und Ausführen der tatsächlichen Logik in C#.Übergabe Zeiger zwischen C++ - Projekt und C# -Projekt ohne Verwendung von unsicheren auf C# -Projekt

Das Übergeben des Werttyps ist sehr praktisch. Aber mit i Referenztyp ist harte Zeit , ohneunsicher oder DllImport Attribut.

C++

Cryptoki.Wrapper.h Datei

using namespace System; 
#pragma comment(lib, "legacy_stdio_definitions.lib") 

namespace CryptokiWrapper {  
    public ref class CryptokiInit 
    { 
    public: 
     char* TESTString(char* test);   
     double TESTDouble(double test);   
    };  
} 

Cryptoki.Wrapper.cpp Datei

#include "stdafx.h" 
#include "Cryptoki.Wrapper.h" 
using namespace std; 
using namespace CryptokiWrapper; 

char* CryptokiInit::TESTString(char* test) 
{ 
    char* r = test;  
    return r; 
} 

double CryptokiInit::TESTDouble(double test) 
{ 
    unsigned long int r = test;  
    return r; 
} 

C# -Code

using System; 
using System.Runtime.InteropServices; 

using CryptokiWrapper; 

namespace CallCryptoki 
{ 
    class Program 
    { 
     //[MarshalAs(UnmanagedType.LPTStr)] 
     //public String msg = "Hello World"; 

     static void Main(string[] args) 
     { 
      CryptokiInit ob = new CryptokiInit(); 
      //This Works 
      doubled d = ob.TESTDouble(99); 

      //But having hard time accepting the char* reference 
      //or sending string as refrence without using unsafe 
      // like 
      string text = "Hello World!"; 
      string res = (*something*)ob.TESTString((*something*)text); 
     } 
    } 
} 

gibt es irgendeine Art von Guss (zB etwas) ..... ist dort sowieso, wo ich diese Aktion leicht durchführen kann. (nur Referenzübertragung ist ausreichend, dann kann ich String oder Objekt erstellen)

Wie bei einer anderen Funktion funktioniert, verwenden Sie die doppelte als Parameter und Rückgabetyp.

Obwohl obiges Beispiel sprechen nur von String, sondern möchte als Konzept verstehen, so dass ich Interop für jeden Referenztyp zwischen zwei Projekt schreiben könnte (d. C# und C++)

Vielen Dank im Voraus für die Hilfe!

+0

http://stackoverflow.com/questions/1658269/char-pointer-from-string-in-c-sharp – SHR

+0

Ändern Sie einfach 'char *' in 'String ^'. Sie können String^in char * und zurück in Ihren C++/CLI-Code konvertieren, viele Fragen dazu. –

Antwort

0

Erstens, das ist nicht einfach C++, aber C++/CLI - die in erster Linie für verwaltete/nicht verwaltete Code-Interoperabilität konzipiert ist.

Ihre C++/CLI-Funktion kann von .NET-String-Typ wie folgt verwenden:

System::String^ TESTString(System::String^ test); 

^ bedeutet verwaltet Referenz, daran zu denken als das verwaltete Äquivalent *.

nun die String-Daten in reinen C++ zu verwenden, haben Sie zwei Möglichkeiten:

  • Marschall es - Overview of Marshaling in C++

    Zum Beispiel sehen, wenn Sie es zu einem const char* konvertieren müssen, tun folgendes:

    #include <msclr/marshal.h> 
    
    msclr::interop::marshal_context ctx; 
    auto testCStr = ctx.marshal_as<const char*>(test); 
    // testCStr is freed when ctx goes out of scope 
    

    Dadurch werden die Zeichenfolgendaten kopiert, da die Speicherrepräsentation von 2 Bytes pro Zeichen in eine einzige geändert werden muss.

  • Zugriff auf den Speicher direkt als const wchar_t*.Sie müssen Pin die Zeichenfolge im Voraus, so dass es nicht vom GC verschoben wird.

    #include <vcclr.h> 
    
    pin_ptr<const wchar_t> testCStr = PtrToStringChars(test); 
    // testCStr behaves just like a const wchar_t* 
    

    Sie nicht die String-Daten auf diese Weise modifizieren.

Um einen String zurück zum verwalteten Seite senden Sie entweder marshal_as<System::String^>(yourCString) verwenden können, oder rufen Sie gcnew System::String(yourCString);