1

I am new to C# and .NET. I want to use my existing C++ dlls within .NET, so I was experimenting with interop. I don't know why this exception is raised. I know what that exception means, I read the MSDN, but not sure why that is raised.

My code is so.

The dll code is a simple function that takes a char*.

extern "C" __declspec(dllexport)void test(char *text)
{
// these raise System.AccessViolationException
// char c = text[0]; 
// int n = strlen(text); 
// char *copy = strdup(text); 
}

The C# code is a simple class calling this function

namespace Interop_test
{
    class Program
    {
        static void Main(string[] args)
        {
            char[] text = new char[10];
            for (int i = 0; i < 10; i++)
                text[i] = (char)('A' + i);
            test(text);
        }
        [DllImport("interop_test_dll.dll")]
        private static extern void test(char[] text);
    }
}

The said exception is raised if the commented out code in the dll function is removed. Why?

How can (or must) I pass an array of data from C# to C++?

Where can I find more information about dealing with memory management during C++/C# interop?

Dirt
  • 181
  • 2
  • 12

4 Answers4

0

Use a string and try this:

private static extern void test(ref string text);

If you want to change your string in your test function then use ref. Otherwise you can leave it.

juergen d
  • 201,996
  • 37
  • 293
  • 362
  • This works for the code shown here, char c = text[0]; but fails for other operations like strdup, strlen etc. – Dirt Feb 08 '12 at 10:30
0

Where do you put a zero at the end of the string? I think no where. I don't know if that is a problem but you can try increasing the size of of text to 11 and then putting a zero in text[10].

Sam Hobbs
  • 83
  • 1
  • 6
0

This should do the trick. CharSet.Ansi and using an actual string. Those are the keys here.

namespace Interop_test
{
    class Program
    {
        static void Main(string[] args)
        {
            char[] text = new char[10];
            for (int i = 0; i < 10; i++)
                text[i] = (char)('A' + i);
            test(new string(text));
        }

        [DllImport("interop_test_dll.dll", CharSet = CharSet.Ansi)]
        private static extern void test(
            [MarshalAs(UnmanagedType.LPStr, CharSet = CharSet.Ansi)] string text);
    }
}
Zenexer
  • 18,788
  • 9
  • 71
  • 77
  • I get this error when I tried. 'System.Runtime.InteropServices.MarshalAsAttribute' does not contain a definition for 'CharSet' – Dirt Feb 08 '12 at 11:15
0

These articles won't answer your specific question but they may come in useful to you as you carry on with this.

Calling Win32 dlls in .NET with P/Invoke

Default Marshalling for value types

Also, in your dllimport statements in additional to indicating the marshalling type, you can add information to indicate if they should be marshalled as input or output or both.

[DllImport("interop_test_dll.dll")]
private static extern void test([MarshalAs(UnmanagedType.LPStr), In, Out]string text);
Nanhydrin
  • 4,332
  • 2
  • 38
  • 51