3

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, ckey, 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.

Simon
  • 1,616
  • 2
  • 17
  • 39

3 Answers3

2

I know this is an old question, but for anyone who stumble upon this question looking for an answer, here are some simpler solutions.

  1. Simply use sprintf to do the conversion like this: sprintf(cStr, "%s", clrString);. See my answer to this question for a complete example.
  2. 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.
Community
  • 1
  • 1
Ionian316
  • 2,303
  • 2
  • 28
  • 36
  • Had this same issue just now. `marshal_as` ended up working beautifully for me, where I was previously having trouble with `Marshal::StringToHGlobalAnsi`. – KChaloux Sep 17 '16 at 23:54
0

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

Sujay Ghosh
  • 2,828
  • 8
  • 30
  • 47
  • As suggested in the link, I tried just to "pin" cKey to avoid GC and passed a char* to the C++-function. But the AccessViolation still occurs. – Simon Dec 09 '10 at 12:07
0

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:

  1. Read here: http://support.microsoft.com/kb/311259
  2. 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.
  3. 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.
Matt Smith
  • 17,026
  • 7
  • 53
  • 103
  • Thanks for the clarification at 2. I tried to use PtrToStringChars (see Edit 2 in my original posting), but the AccessViolation still occurs. Unfortunately methodX() is from a Third-party-DLL, so no source code and only poor documentation. I just get a trace, that the method has been entered with the values of a, key, and v. – Simon Dec 10 '10 at 08:08
  • To eliminate the possibility that methodX is the problem, have you tried passing in a natively allocated char * (actually, it looks like your edit 2 tries this out)? If you're getting a TRACE that the method has been entered, then I'd suspect methodX is the culprit (or you are passing it something it doesn't expect). – Matt Smith Dec 10 '10 at 15:04
  • Yes, I assume the problem is in methodX as well. I just wanted to make sure, there's no error in the wrapper. Thanks for your help. – Simon Dec 13 '10 at 09:20