none
c++ std::map<std::string, std::vector<std::string>> &dataStrings) to c# TYPE RRS feed

  • Question

  • What is the type in c# conversion type from c++. I am using this input in c++ "std::map<std::string, std::vector<std::string>> &dataStrings)" and trying to call this function into csharp

    C++ EXPORT

    DECLDIR int  GetColor(char* filename, double num, std::map<std::string, std::vector<std::string>> &dataStrings);

    C# IMPORT: I don't know to name or what type to use in c#  for the import 3rd parameter "dataStrings"

     [DllImport(@"..\ThirdParty\ColorAPI.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]

            public static extern int GetColor(string filename, double num, ???? dataStrings);


    pianoboyCoder

    Thursday, November 1, 2018 5:59 PM

All replies

  • What is the type in c# conversion type from c++. I am using this input in c++ "std::map<std::string, std::vector<std::string>> &dataStrings)" and trying to call this function into csharp

    C++ EXPORT

    DECLDIR int  GetColor(char* filename, double num, std::map<std::string, std::vector<std::string>> &dataStrings);

    C# IMPORT: I don't know to name or what type to use in c#  for the import 3rd parameter "dataStrings"

     [DllImport(@"..\ThirdParty\ColorAPI.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]

            public static extern int GetColor(string filename, double num, ???? dataStrings);


    pianoboyCoder

    The marshaling performed in connection with using P/Invoke to call an unmanaged function from C# doesn't know anything about the container classes used by the Standard C++ Library.

    As I indicated in your other thread at https://social.msdn.microsoft.com/Forums/vstudio/en-US/0571edc7-fd2d-42ab-af25-a1122993fb30/how-to-pass-a-list-from-a-c-dll-to-c?forum=vcgeneral, you need to expose the data from the unmanaged function using a data type that the framework knows how to marshal.

    Again, I refer you to Marshaling Data with Platform Invoke

    Thursday, November 1, 2018 6:09 PM
  • You cannot call a function in C++ that uses C++-only types from managed code. You actually cannot do it from any language. Exporting it and marking it as extern "C" changes nothing. The type cannot be created outside the C++ process it is defined in and therefore cannot be used directly. However you could create something in C++ and return it to managed code (or any language) as a pointer and then pass that pointer back to C++ later. This is a common approach used for opacity.

    //C++ side
    void* CreateCppObject ();
    
    void DoSomethingWithCppObject ( void* pObject );
    
    //C# side
    private static extern IntPtr CreateCppObject ();
    private static extern void DoSomethingWithCppObject ( IntPtr ptr );
    
    var obj = CreateCppObject();
    DoSomethingWithCppObject(obj);
    

    In C++ a ref parameter (&) is technically a pointer so you could use IntPtr on the C# side but ref parameters in C++ cannot be null so that map would have to have been created in C++ already otherwise it'll crash when C++ tries to use it.

    Personally I would recommend finding an alternative approach that doesn't require the C++ code at all. But if you really need to use a C++ DLL and you cannot change the signature then you're only real option is to create a wrapper. You can create a C++ wrapper that uses the other C++ library but exposes functions that work with managed code. Alternatively you could use C++/CLI which is designed to solve these problems as well.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, November 1, 2018 6:17 PM
    Moderator
  • we have to use c++ code at this point.

    Are you saying do this in c++ below as far as returning type goes?

    c++:

    &std::map<std::string, std::vector<std::string>> GetColor(char* filename, double num{

    }

    C#:

         [DllImport(@"@"..\ThirdParty\ColorAPI.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
            public static extern "TYPE???" GetColor(string filename, double num);


    pianoboyCoder

    Thursday, November 1, 2018 6:29 PM
  • If you look carefully at the examples posted by CoolDadTx you will note that an IntPtr is both returned from C++ to C# and then passed back from C# to C++.  All actual processing is performed on the C++ side.

    In your case, returning a pointer to Standard C++ Library objects from C++ to C# is pointless.  C# can receive the IntPtr, but it won't be able to do anything with it.

    Thursday, November 1, 2018 6:46 PM
  • Ok. Can you tell me how to pass this type below from c++ to c#. Does the std::map type have to be an input parameter?

    I need to get this collection or map back from the c++ DLL. Is there anyway?


    pianoboyCoder


    Thursday, November 1, 2018 6:56 PM
  • Ok. Can you tell me how to pass this type below from c++ to c#. Does the std::map type have to be an input parameter?

    pianoboyCoder


    Can't be done.  Forget about using objects from the Standard C++ Library directly in C#.  I suggest you look into creating a dll using C++/CLI to serve as an intermediary between C# and C++.
    Thursday, November 1, 2018 6:58 PM
  • My DLL is a wrapper. Im just having an issue of getting the std::map marshalled into C#? Is this possible?

    pianoboyCoder

    Thursday, November 1, 2018 6:59 PM
  • My DLL is a wrapper. Im just having an issue of getting the std::map marshalled into C#? Is this possible?

    pianoboyCoder


    Did you read the link on marshaling that I previously posted for you  (twice!).
    Thursday, November 1, 2018 7:00 PM
  • Yes may im not understanding it RLWA32? 

    pianoboyCoder

    Thursday, November 1, 2018 7:33 PM
  • OK,  then answer this -- when you look at the marshaling documentation do you see anything about how the framework marshals Standard Library C++ objects to managed code?
    Thursday, November 1, 2018 7:37 PM
  • Yes I am currently marshalling functionality and types successfully. My failure is when I get to one particular function to marshall the std::map from c++ to c#. I get the error you cannot marshall generic types. The eqivualent from a c++ std::map is c# dictionary. But I have no way of marshalling the dictionary. This is my struggle at the moment.

    I don't know how to marchall the input parameter in bold print below.

     GetColor(char* filename, double num, std::map<std::string, std::vector<std::string>> &dataStrings)



    pianoboyCoder

    Thursday, November 1, 2018 8:09 PM
  • Can you post this code you said you have working so we can see how you're doing it. This would likely reveal the solution. And no you cannot use a C# dictionary as it in no way resembles a std::map.

    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, November 1, 2018 8:14 PM
    Moderator
  • Yes I am currently marshalling functionality and types successfully. My failure is when I get to one particular function to marshall the std::map from c++ to c#. I get the error you cannot marshall generic types. The eqivualent from a c++ std::map is c# dictionary. But I have no way of marshalling the dictionary. This is my struggle at the moment.

    I don't know how to marchall the input parameter in bold print below.

     GetColor(char* filename, double num, std::map<std::string, std::vector<std::string>> &dataStrings)



    pianoboyCoder

    Nonsense.  There is absolutely nothing about marshaling Standard C++ Library containers (e.g., std::vector, std::map, etc.) at https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-data-with-platform-invoke#platform-invoke-data-types

    • Edited by RLWA32 Thursday, November 1, 2018 8:18 PM fix typo
    Thursday, November 1, 2018 8:17 PM
  • My point exactly.  How can get pass this error.  In my c++ DLL I have a std::map, and in my c# I am using Dictionary. What do I use? 

    C++ Code

    C# Code



    pianoboyCoder

    Thursday, November 1, 2018 8:26 PM
  • My point exactly.  How can get pass this error.  In my c++ DLL I have a std::map, and in my c# I am using Dictionary. What do I use? 

    C++ Code

    C# Code



    pianoboyCoder

    You've already been told that you need to use plain old data types or a C++/CLI intermediary.  Asking the same question over and over doesn't change the answer.
    Thursday, November 1, 2018 8:31 PM
  • New question. So what data type is equivalent to the dictionary that I am trying to use to make this work?

    pianoboyCoder

    Tuesday, November 6, 2018 12:18 AM
  • The closest equivalent to a map in C++ would be a Dictionary or Hashset in .NET depending upon duplicates and whatnot.

    But to be clear, no amount of P/Invoke magic will get you to be able to pass a Dictionary/Hashset to a C++ function or vice versa. They have completely unrelated internal structures and are not compatible. You would have to do the translation in something that had access to both such as C++/CLI. 

    The only other options that come to mind are:

    • Create C++ functions to get/set key-value pairs. Then have the .NET code call them for each value in the dictionary. Same goes for the C++ code.
    • Create a memory object that has the key-value pairs defined in a simple structure that both C++ and C# can access. Then use P/Invoke to pass the array of key-value pairs to/from the other side. Then write code on both sides to read/write that array.

    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, November 6, 2018 1:12 AM
    Moderator
  • Wendy Zang,

    Thanks you so much. Could you provide me a small c++ application that will do what you mention. I am a visual learner. It can be one small function that's exported that will do exactly what you mention below. I just a small sample project to see what you talking about. I am c# developer, and I haven't work in c++ in 6 years. So at the moment I am having a hard understanding. I really need to see an example from the c++ perspective.

    Provide a Small c++ Example below:

    Create a memory object that has the key-value pairs defined in a simple structure that both C++ and C# can access. Then use P/Invoke to pass the array of key-value pairs to/from the other side. Then write code on both sides to read/write that array.


    pianoboyCoder

    Thursday, November 8, 2018 5:44 PM
  • Hi pianboyCoder,

    Sorry for that. I do not know C++ well. If you want a C++ application, you could post a new thread in C++ forum.

    https://social.msdn.microsoft.com/Forums/en-US/home?forum=vcgeneral&filter=alltypes&sort=lastpostdesc

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 16, 2018 7:48 AM
    Moderator