0

Stuck in very naive issue. I have two project, One in C++ and other in C#. Idea is to use C++ project as wrapper around some C libs. and performing actual logic in C#.

Passing the Value type is very convenient. But with reference type i am having hard time WITHOUT USING unsafe or DllImport attribute.

C++

Cryptoki.Wrapper.h File

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 File

#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);
        }
    }
}

IS there any type of cast (i.e. something) ..... is there anyway where i am able to easily perform this action. (only reference transfer will be sufficient, then i can build string or object)

Like on another function works, using the double as parameter and return type.

Though above example speak of string only, but would like to understand as concept so that i could write interop for any reference type between two project(i.e. C# and C++)

Thanks in advance for help!

2
  • stackoverflow.com/questions/1658269/… Commented Apr 3, 2016 at 9:14
  • Simply change char* to String^. You can easily convert String^ to char* and back in your C++/CLI code, many existing questions about it. Commented Apr 3, 2016 at 9:22

1 Answer 1

1

First, that's not plain C++, but C++/CLI - which is primarily designed for managed/unmanaged code interoperability.

Your C++/CLI function can use .NET's string type like this:

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

^ means managed reference, think of it as the managed equivalent of *.

Now, to use the string data in pure C++, you have two choices:

  • marshal it - see Overview of Marshaling in C++

    For instance, if you need to convert it to a const char*, do the following:

    #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
    

    This will copy the string data, as the memory representation needs to change from 2 bytes par character to a single one.

  • access the memory directly as const wchar_t*. You need to pin the string beforehand so it's not moved by the GC.

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

    Do not modify the string data this way.

To send a string back to the managed side, you can either use marshal_as<System::String^>(yourCString), or call gcnew System::String(yourCString);

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.