Using C++ native dll in .Net External component has thrown an exception

I'm trying to use a native C++ dll in C# and am getting the "External component has thrown an exception" with an error code of -2147467259.

C#:

[DllImport(@"MyDLL.dll", CharSet = CharSet.Auto)]
public static extern string MyFunction([MarshalAs(UnmanagedType.LPStr)] StringBuilder input);

C++:

__declspec(dllexport) char * __stdcall MyFunction(const char* inputPtr);

The function works just fine in C++. How can I track this error down? I have tried using string and string builder for the parameter.

Update

I found this article http://tom-shelton.net/index.php/2008/12/11/creating-a-managed-wrapper-for-a-lib-file/

It details a way to use managed C++ to wrap an unmanaged static library in C++ which can then be used in a managed language. Would this be a good way of going about tackling this problem? Can the lib be an unmanaged dll?


尝试从http://blog.rednael.com/2008/08/29/MarshallingUsingNativeDLLsInNET.aspx - 这已经保存了几天:-)的技术


If the parameter is in-only (and not out), stringbuilder is not required. If it's an out parameter (or ref) you should use stringbuilder and pre-allocate the buffer using stringbuilder constructor.

I can guess the problem is that you are returning an Ansi string instead of the expected unicode string. This cause the default pinvoke marshaler to read too much memory.

Try this: [DllImport(@"MyDLL.dll", CharSet = CharSet.Auto)] [return : MarshalAs(UnmanagedType.LPStr)] public static extern string MyFunction([MarshalAs(UnmanagedType.LPStr)] string input);

In any case, in the vast majority of times, it does not make any sense to write Ansi C++ code. I would suggest to convert the C++ code to unicode only (not tchar but wchar_t).


CharSet = CharSet.Auto?? use CharSet.Ansi

You cannot use a char array as return, a block of memory allocated with c++ cannot be used by C#! In your case you probably need to copy it into C# managed memory. Use StringBuilder for that or MarshalAs attribute that will copy for you the buffer into C# managed memory.

You have to change your C++ function, your C++ function must write into the destination buffer that must be allocate so it contains at least the number of characters you need plus one (for null termination character).

[DllImport(@"MyDLL.dll", CharSet = CharSet.Ansi)]
private static extern void MyFunction([MarshalAs(UnmanagedType.LPStr)] string input, StringBuilder result);

public static string MyFunctionPublic(string input)
{
    StringBuilder sb = new StringBuilder(input.Length + 1);
    MyFunction(input, sb);
    return sb.ToString();
}

And i expect your C function to do something like this:

void __stdcall MyFunction(const char* input, char* result)
{
    strcpy(result, input); // this is a dummy stupid code to show how it works.
}

Probably you will need a function that gives you idea of how much bytes you have to allocate in C#. This function can be something like this:

int __stdcall ComputeMyFunctionBytes(const char* input)
{
    return strlen(input); // this is a dummy stupid code to show how it works.
}

Never return a piece of allocated memory to C#, it cannot do anything with that, nor deallocating, nor reading and nor writing, until you use unsafe code, but this is not what you are trying to do.

A good article seems to be here: http://www.devx.com/dotnet/Article/6990/1954

Also note that C# uses unicode, 16 bit per character, so it will be converted from ansi to unicode.

链接地址: http://www.djcxy.com/p/44452.html

上一篇: 如何在Windows 7中调用win32 dll

下一篇: 在.Net外部组件中使用C ++本机DLL会引发异常