I've written a C++/CLI wrapper for a C++-DLL to use this DLL in a C# programm.
However, when I call a function, which takes a char* I get a AccessViolation
int Wrapper::Net_methodX(int a, String^ key, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
int val = methodX(a,cKey, v); // AccessViolation here
Marshal::FreeHGlobal(ptr);
return val;
}
The signature of the C++-function is
int methodX(int a, char *Key, long v);
EDIT 1
Just to "pin" like the following didn't work either:
int Wrapper::Net_methodX(int a, String^ key, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
char* cKey = static_cast<char*>(ptr.ToPointer());
pin_ptr<char> pinned = cKey;
int val = methodX(a,cKey, v);
Marshal::FreeHGlobal(ptr);
return val;
}
EDIT 1 END
EDIT 2
I tried also PtrToStringChars the following way (Thanks Matt, found also some doc here):
int Wrapper::Net_methodX(int a, String^ key, long v)
{
pin_ptr<const wchar_t> wkey = PtrToStringChars(key);
size_t convertedChars = 0;
size_t sizeInBytes = ((key->Length + 1) * 2);
errno_t err = 0;
char * ckey = (char * ) malloc(sizeInBytes);
err = wcstombs_s(&convertedChars, c开发者_如何学JAVAkey, sizeInBytes, wkey, sizeInBytes);
int val = methodX(A_Symbol_Table,ckey, Value);
return val;
}
AccessViolation still occurs, maybe it's an error in methodX() (which is a Third-party-DLL).
EDIT 2 END
I have read some related questions here, but did not find a solution yet.
Any hints? Thank you.
I know this is an old question, but for anyone who stumble upon this question looking for an answer, here are some simpler solutions.
- Simply use
sprintf
to do the conversion like this:sprintf(cStr, "%s", clrString);
. See my answer to this question for a complete example. - Read KB311259 as suggested by Matt Smith. If you are using VS 2008 or higher, use
marshal_as<>
(Method #4 in the KB). It's much simpler than the other methods in that document.
Simon, I tried out your example and I do not get an Access Violation. Here's my code:
using namespace System;
using namespace System::Runtime::InteropServices;
ref class Wrapper
{
public:
static int Net_methodX(int a, String^ key, long v);
};
int methodX(int a, char * pKey, long v)
{
IntPtr ptr = static_cast<IntPtr>(pKey);
String ^ pString = Marshal::PtrToStringAnsi(ptr);
System::Console::WriteLine(pString);
return a;
}
int Wrapper::Net_methodX(int a, String^ pKey, long v)
{
IntPtr ptr = Marshal::StringToHGlobalAnsi(pKey);
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
int val = methodX(a,cKey, v); // AccessViolation here
Marshal::FreeHGlobal(ptr);
return val;
}
void main()
{
Wrapper wrapper;
String ^ p = gcnew String("Hello");
wrapper.Net_methodX(0, p, 0);
}
Also, I have a few comments:
- Read here: http://support.microsoft.com/kb/311259
- You are using a pin_ptr to native memory. The StringToHGlobalAnsi method returns native memory, so I don't think using a pin_ptr makes sense here. A pin_ptr would make sense if you were using a method that gives you back a pointer to managed memory (like PtrToStringChars). Unless you are modifying the string, you probably want to go with the PtrToStringChars approach anyways--to avoid unnecessary allocation and copying.
- Would you post an example version of methodX that causes the problem? If I can reproduce the issue, I might be able to be more helpful.
Simon
I think there is a problem with the following code
pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
You might want to read this http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b9f6-c8f5107bc957
Let me know if it helped you.
Sujay
精彩评论