2009-12-01 23 views
11

C++ ile gerçekten paslı, biraz paslıyım. Üniversitenin birinci sınıfından beri ona dokunmadım, bu yüzden bir süredir. Her neyse, çoğu insanın yaptığı şeyin tersini yapıyorum. C++ 'dan C# kodu aranıyor. İnternette biraz araştırma yaptım ve bir köprü oluşturmak için bazı yönetilen C++'ları oluşturmam gerektiği gibi görünüyor. __declspec (dllexport) kullanın ve bundan sonra bir dll oluşturun ve her şeyi bir sarıcı olarak kullanın.C++ ve C++ arasında bir köprü oluşturmak için C++ Yönetilen C++

Ama benim sorunum - Örnek bulmakta zorlanıyorum. Birisi C# sürümünü String.ToUpper() kullanmak istedim bazı temel şeyler buldum ama bu çok temel ve sadece küçük bir kod parçacığı oldu.

Biraz daha somut bir şey bulabileceğim herhangi bir fikrim var mı? Not, COM kullanmak istemiyorum. Amaç, C# koduna hiç dokunmamaktır.

+0

Yönetilmeyen C/C++ ile karşılaşmak istediğiniz arabirim ne kadar karmaşık? – CuppM

+0

Benzer bir soru/cevap için bu bağlantıya bakın: http://stackoverflow.com/questions/13293888/how-to-call-ac-sharp-library-from-native-c-using-c-cli-and-ijw . – amalgamate

cevap

11

, her ihtimale karşı nasıl olsa onu göndeririz ...

kendi kitaplığınızı erişmek için bir sarıcı yazma sürecini standart .Net kitaplıklarından birine erişmekle aynıdır. CsharpProject adlı bir projede

Örnek C# sınıfı kodu:

using System; 

namespace CsharpProject { 
    public class CsharpClass { 
     public string Name { get; set; } 
     public int Value { get; set; } 

     public string GetDisplayString() { 
      return string.Format("{0}: {1}", this.Name, this.Value); 
     } 
    } 
} 

Yönetilen C++ sınıf kütüphanesi projesi oluşturmak (örnek CsharpWrapper olan) ve buna bir referans olarak C# projesi eklersiniz. Aynı başlık dosyasını dahili kullanım ve referans projede kullanmak için doğru declspec'i kullanmanın bir yoluna ihtiyacınız var. Bu, bir önişlemci yönergesini (bu durumda CSHARPWRAPPER_EXPORTS) tanımlayarak ve bir makro dosyasına C/C++ arabiriminizdeki dışa aktarma makrosunu ayarlamak için #ifdef kullanarak yapılabilir. Yönetilmeyen arabirim üstbilgi dosyası, yönetilmeyen öğeler içermeli (veya önişlemci tarafından filtrelenmiş olmalıdır).

Yönetilmeyen C++ Arabirim Üstbilgi dosyası (CppInterface.h): yönetilen kitaplık dosyalarınıza eklenebilecek bir iç başlık dosyası oluşturabilirsiniz. Bu, using namespace ifadelerini ekleyecektir ve ihtiyacınız olan yardımcı işlevleri içerebilir.

yönetilen C++ Arayüz Başlık dosyası (CsharpInterface.h):

#pragma once 

#include <string> 

// .Net System Namespaces 
using namespace System; 
using namespace System::Runtime::InteropServices; 

// C# Projects 
using namespace CsharpProject; 


////////////////////////////////////////////////// 
// String Conversion Functions 

inline 
String^ToManagedString(const char * pString) { 
return Marshal::PtrToStringAnsi(IntPtr((char *) pString)); 
} 

inline 
const std::string ToStdString(String^strString) { 
IntPtr ptrString = IntPtr::Zero; 
std::string strStdString; 
try { 
    ptrString = Marshal::StringToHGlobalAnsi(strString); 
    strStdString = (char *) ptrString.ToPointer(); 
} 
finally { 
    if (ptrString != IntPtr::Zero) { 
    Marshal::FreeHGlobal(ptrString); 
    } 
} 
return strStdString; 
} 

Sonra sadece sarma yapar Arayüz kodu yazmak.

yönetilen C++ Arayüz Kaynak dosyası (CppInterface.cpp):

#include "CppInterface.h" 
#include "CsharpInterface.h" 

std::string GetDisplayString(const char * pName, int iValue) { 
CsharpClass^oCsharpObject = gcnew CsharpClass(); 

oCsharpObject->Name = ToManagedString(pName); 
oCsharpObject->Value = iValue; 

return ToStdString(oCsharpObject->GetDisplayString()); 
} 

Sonra sadece yönetilmeyen projede yönetilmeyen başlığını bağlarken oluşturulan .lib dosyasını kullanmak için bu linker söyleyecektir ve emin olun içerir .Net ve sarmalayıcı DLL'leri, yönetilmeyen uygulamanızla aynı klasörde.

#include <stdlib.h> 

// Include the wrapper header 
#include "CppInterface.h" 

void main() { 
// Call the unmanaged wrapper function 
std::string strDisplayString = GetDisplayString("Test", 123); 

// Do something with it 
printf("%s\n", strDisplayString.c_str()); 
} 
+0

Bir şeyleri biraz daha açıkladın - keşke her iki cevabı da seçebilirdim. Teşekkürler! –

+0

Dizeler, yerelden yönetilen bir dizgeyi yönetmeye gereksinim duyduğunuz anda dönüşüm işlevleri gerekli olduğunda iyi bir örnektir (normalde çoğu etkileşimde oldukça kısadır!) – Iain

+0

"Böyle bir dosya veya dizin yok" için, gerekir ya: 1) Yönetilmeyen uygulamaya 'CppInterface.h' ekleyin. Tüm projeler aynı yerde/depoda yaşıyorsa bunu yapmam. Daha sonra korumak için çift dosyaları var. 2) Yönetilmeyen uygulamanın derleme içerme klasörü altındaki sarmalayıcı projesinin dosyalarının yolunu ekleyin. Visual Studio için, projeye sağ tıklayın ve "Özellikler" i seçin. Daha sonra "Yapılandırma Özellikleri" -> "C/C++" -> "Genel" -> "Ek İçerilen Dizinler" altında, "CppInterface.h" konumunun yolunu ekleyin. – CuppM

10

Görsel stüdyosunda yeni bir C++/CLI projesi oluşturun ve C# dll dosyanıza bir başvuru ekleyin.

namespace DotNetLib 
{ 
    public class Calc 
    { 
     public int Add(int a, int b) 
     { 
      return a + b; 
     } 
    } 
} 

Şimdi C++/CLI proje bir CLR C++ sınıfı ekleyin:

// TestCPlusPlus.h 

#pragma once 

using namespace System; 
using namespace DotNetLib; 

namespace TestCPlusPlus { 

    public ref class ManagedCPlusPlus 
    { 
    public: 
     int Add(int a, int b) 
     { 
      Calc^ c = gcnew Calc(); 
      int result = c->Add(a, b); 
      return result; 
     } 
    }; 
} 

Bu C'den C# arayacak ++ biz bu sınıfla DotNetLib.dll adlı bir C# dll var varsayalım.

Şimdi CLR C++ sınıfına konuşabilirsiniz C++/CLI proje için bir doğal C++ sınıfı ekleyebilirsiniz gerekirse:

// Native.h 
#pragma once 

class Native 
{ 
public: 
    Native(void); 
    int Add(int a, int b); 
    ~Native(void); 
}; 

ve:

// Native.cpp 
#include "StdAfx.h" 
#include "Native.h" 
#include "TestCPlusPlus.h" 

Native::Native(void) 
{ 
} 

Native::~Native(void) 
{ 
} 

int Native::Add(int a, int b) 
{ 
    TestCPlusPlus::ManagedCPlusPlus^ c = gcnew TestCPlusPlus::ManagedCPlusPlus(); 
    return c->Add(a, b); 
} 

Sen gerekir Native sınıfını başka bir yerel C++ dll'sinden normal olarak çağırır.

Ayrıca Yönetilen C++, farklı ve C++/CLI tarafından başarılı oldu. Vikipedi onu en iyi açıklıyor: lain bir örnek yazmaya beni yendi iken

İlgili konular