====Syntaxe de C++/CLI==== Les types ''C#'' se postfixe avec un ''^'' et on utilise ''using namespace'' à la place de ''using'' pour faire la différence avec le ''C++''. using namespace System::Threading; Mutex^ mutex; Une classe est autorisée à utiliser les types C# si sa déclaration est précédée de ''ref''. public ref class Carte {} L'initialisation des variables statiques d'une classe doit se faire dans l'entête et l'allocation mémoire se faire avec un ''gcnew''. public ref class Driver { static System::Collections::Generic::List^ cartes = gcnew System::Collections::Generic::List(); La notion de référence ''&'' n'existe pas pour les objets managés. ====C# => C++==== ===Pointeurs=== [[https://stackoverflow.com/questions/25600940/managed-c-cli-array-conversion-error|Managed C++/CLI Array Conversion Error]] {{ :lang:csharp:clr:c_cli_-_managed_c_cli_array_conversion_error_-_stack_overflow_2019-12-13_3_13_20_pm_.html |Archive du 01/09/2014 le 13/12/2019}} * C# CalcSumArray(new[] { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f }, 6); * CLR C'est ''cli::pin_ptr'' qui fait office de ''GC::StillAlive()'' et donc ''val'' ne sera pas purgé tant que ''pin_ptr'' est en vie.
An object is pinned only while a pin_ptr points to it. The object is no longer pinned when its pinning pointer goes out of scope, or is set to nullptr. After the pin_ptr goes out of scope, the object that was pinned can be moved in the heap by the garbage collector. [[https://docs.microsoft.com/en-us/cpp/windows/pin-ptr-cpp-cli?view=vs-2017|pin_ptr (C++/CLI)]] {{ :lang:csharp:clr:pin_ptr_c_cli_microsoft_docs_2019-12-13_3_13_28_pm_.html |Archive du 12/10/2018 le 13/12/2019}}
static float CalcSumArray(array^ val, int length) { cli::pin_ptr t = &val[0]; float* y = t; return SumArray(y, length); } * C++ float SumArray(float* val, int length); ===Marshaling=== ^From type ^To type ^Marshal method ^Include file^ |System::String%%^%% |const char * |marshal_context |marshal.h| |System::String%%^%% |const wchar_t* |marshal_context |marshal.h| |System::IntPtr |HANDLE |marshal_as |marshal_windows.h| |System::String%%^%% |BSTR |marshal_context |marshal_windows.h| |System::String%%^%% |bstr_t |marshal_as |marshal_windows.h| |System::String%%^%% |std::string |marshal_as |marshal_cppstd.h| |System::String%%^%% |std::wstring |marshal_as |marshal_cppstd.h| |System::String%%^%% |CStringT |marshal_as |marshal_atl.h| |System::String%%^%% |CStringT |marshal_as |marshal_atl.h| |System::String%%^%% |CComBSTR |marshal_as |marshal_atl.h| Exemple : #include System::String^ managed = "test"; std::string unmanaged = msclr::interop::marshal_as(managed); [[https://docs.microsoft.com/en-us/cpp/dotnet/overview-of-marshaling-in-cpp?view=vs-2017|Overview of Marshaling in C++]] {{ :lang:csharp:clr:overview_of_marshaling_in_c_microsoft_docs_2019-12-13_3_13_36_pm_.html |Archive du 12/07/2019 le 13/12/2019}} ====C++ => C#==== ===Marshaling=== ^From type ^To type ^Marshal method ^Include file^ |const char * |System::String%%^%% |marshal_as |marshal.h| |char * |System::String%%^%% |marshal_as |marshal.h| |const wchar_t * |System::String%%^%% |marshal_as |marshal.h| |wchar_t * |System::String%%^%% |marshal_as |marshal.h| |HANDLE |System::IntPtr |marshal_as |marshal_windows.h| |BSTR |System::String%%^%% |marshal_as |marshal.h| |bstr_t |System::String%%^%% |marshal_as |marshal_windows.h| |std::string |System::String%%^%% |marshal_as |marshal_cppstd.h| |std::wstring |System::String%%^%% |marshal_as |marshal_cppstd.h| |CStringT |System::String%%^%% |marshal_as |marshal_atl.h| |CStringT |System::String%%^%% |marshal_as |marshal_atl.h| |CComBSTR |System::String%%^%% |marshal_as |marshal_atl.h| ===struct=== struct Argument { int age; char name[50]; } ; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Argument { public int age; [MarshalAs(UnmanagedType.LPStr, SizeConst = 50)] public string name; // fixed char name[50]; // Autre possibilité } ===Prototype=== ^C++/CLI ^C# généré ^ |''uint8_t'' |''byte'' | |''array%%^%%'' |''byte[]'' | |''System::String%%^%%'' |''string'' | |''System::String%%^%%%'' |''ref string''| |''[System::Runtime::InteropServices::Out]System::String%%^%%%''|''out string''| |''[System::Runtime::InteropServices::In]System::String%%^%%%'' |''ref string''| |''float'' |''float'' | |''float&'' |''float*'' | |''float%'' |''ref float'' | ====Erreurs==== * '''IServiceProvider': ambiguous symbol'' Il ne faut pas mettre ''using namespace System;'' avant la déclaration de ''#include ''. * '''msclr::interop::marshal_as': none of the 3 overloads could convert all the argument types'' Il ne faut pas tenter d'utiliser directement un attribut d'une classe. Il faut passer par une variable locale : System::String^ fic = fichier_; std::string tt = msclr::interop::marshal_as(fic); * '''XXX.YYY(?)' is not supported by the language'' Apparaît dans le projet C# en essayant d'appeler une fonction du projet ''C++/CLI''. Dans le projet ''C++/CLI'', il manque le ''^'' après le type à la place du ''?''. [[https://qualapps.blogspot.com/2008/07/using-atlstrh-in-managed-project.html|Fixing "ambiguous symbol" in a C++/CLR project]] {{ :lang:csharp:clr:technical_blog_for_jim_beveridge_fixing_ambiguous_symbol_in_a_c_clr_project_2019-12-13_3_13_44_pm_.html |Archive du 11/07/2008 le 13/12/2019}}