Marshalling string from c# to c++

家住魔仙堡 提交于 2019-12-04 05:52:10

问题


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 Init( 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


回答1:


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




回答2:


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




回答3:


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




回答4:


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


来源:https://stackoverflow.com/questions/4736894/marshalling-string-from-c-sharp-to-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!