开发者

Marshalling string from c# to c++

开发者 https://www.devze.com 2023-02-06 02:04 出处:网络
I am new in microsoft world. I have lot of problem trying to pass a simple string from c# to dll/c++ I have read a lot of post and documentation about but the problem is the same.

I am new in microsoft world. I have lot of problem trying to pass a simple string from c# to dll/c++ I have read a lot of post and documentation about but the problem is the same.

C++ code

extern "C" __declspec(dllexport) int In开发者_如何学编程it( long l , char* url );

C# code

[DllImport("MCRenderer.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]
    public static extern int Init(long a, StringBuilder url);


Init(hndl.ToInt64(), str );

what haeppen is that long value is passed correctly while string parameter is

0x00000000 <Bad Ptr>

can you help me ... Iam really confused thanks!! AG


You should pass a string, url should be of type string and not StringBuilder.


It's because you're marshalling incorrectly: long and int in C++ are both (usually) int in C#.


From MSDN, you need to:

The only caveat is that the StringBuilder must be allocated enough space for the return value, or the text will overflow, causing an exception to be thrown by P/Invoke

Also from Marshaling between Managed and Unmanaged Code

  • Don't pass StringBuilder by reference (using out or ref). Otherwise, the CLR will expect the signature of this argument to be wchar_t ** instead of wchar_t *, and it won't be able to pin StringBuilder's internal buffer. Performance will be significantly degraded.
  • Use StringBuilder when the unmanaged code is using Unicode. Otherwise, the CLR will have to make a copy of the string and convert it between Unicode and ANSI, thus degrading performance. Usually you should marshal StringBuilder as LPARRAY of Unicode characters or as LPWSTR.
  • Always specify the capacity of StringBuilder in advance and make sure the capacity is big enough to hold the buffer. The best practice on the unmanaged code side is to accept the size of the string buffer as an argument to avoid buffer overruns. In COM, you can also use size_is in IDL to specify the size.

So in your example, you need to specify the native size as the parameter of the StringBuilder like this StringBuilder str = new StringBuilder(SIZE_OF_NATIVE_STRING);


Try using LPCSTR in the dll function parameter

extern "C" __declspec(dllexport) int Init( long l , **LPCTSTR** url );

Here is a good example that I found on how to do this.

C++:

extern "C" __declspec(dllexport) void doSomething(LPCTSTR asString)
{
    std::cout << "here" << (wchar_t)asString << endl;
    system ("pause");
}

C#:

class Program
{
    static void Main(string[] args)
    {
        String myString = "String in C#";
        doSomething(myString);
    }
    private const String path = @"C:\testdll2.dll"; //Make sure that the DLL is in this location

    [DllImport(path)]
    private static extern void doSomething(string asString);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号