简体   繁体   中英

Calling C# function from C++/CLI - Convert Return C# string to C String

I have a C# function that I made into a DLL:

public static string Test(string name)
{
    return "Hello " + name;
}

In C++/CLI project I successfully import that DLL, now I want to have a way to call that function and make it available for normal unmanaged C++. So I want to export the C++/CLI function like this:

extern "C" __declspec(dllexport)
void __stdcall Example(char* name, char* greet) {
    // name will be passed to C# Test(...) function
    // and greet will contains the returned value

    // call to the C# function here:
    ...
}

I dont care what the C++/CLI function looks like, as long as i can export it to normal unmanaged C++.

** Edit: as someone complain about my question, I only need to know how you can call the C# function, given a C string, and how to retrieve the returned result and store it in another C string. It's not like a "problem", it's like a newbie who don't know how to code, and come here to ask... Thank you **

** Edit2: now i noticed, someone has edited my post (i dont know, a moderator or someone...). Now when i re-read my post, even i don't know what the post trying to ask... Please, i think you shouldn't do that **

With C++/CLI you have everything you need at your disposal.

You could do it this way:

#include <string>
#include <msclr\marshal_cppstd.h>

extern "C" __declspec(dllexport)
void __stdcall Example(char* name, char* greet) {
    // name will be passed to C# Test(...) function
    // and greet will contains the returned value

    // Create new System::String^ from char*
    System::String^ clrString = msclr::interop::marshal_as<System::String^>(name);

    // Call C# function
    System::String^ result = Test(clrString);

    // Create new std::string from System::String^
    std::string cppString = msclr::interop::marshal_as<std::string>(result);

    // Copy C++-string to the destination
    strcpy(greet, cppString.c_str());
}

This solution uses std::string . You can also use a marshal_context to directly convert between System::String and char[] , but I prefer to use std::string since it saves you some typing and there is less to go wrong.

Of course, one can shorten this down to:

strcpy(greet, marshal_as<string>(Test(marshal_as<String^>(name))).c_str());

Or even further, since System::String has a constructor accepting char* :

strcpy(greet, marshal_as<string>(Test(name)).c_str());

Have a look here for more info about marshalling: http://msdn.microsoft.com/en-us/library/bb384865.aspx

Important: C# uses dynamic strings and C# code often happily generates very long strings, resulting in a crash or worse if the memory pointed to by greet is not large enough to contain the string. A common way to deal with this is to change the signature of Example to something like this:

void __stdcall Example(char* name, char* greet, size_t destBufferSize)

And check if the destBufferSize is large enough to contain the resulting string or truncate the value using strncpy or similar methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM