views:

51

answers:

2

Hello, I wave a method in C++ that receives a parameter of the LPCOLESTR type. I'm accessing this method through C#, but I can't make the correct conversion between String and this type.

Let's say the method signinature in C++ is:

void Something(LPCOLESTR str)

In C#, I'm trying to call it (all reference issues to access the method through a DLL have been solved already):

String test = "Hello world";
Something(test);

But with no luck, of course. If anyone can help me, I'd be very glad. Thank you!


Code snippet:

As an example, here's my C++ portion of code, defined in the file MixedCodeCpp.h (CLR Class Library)

#include "windows.h"  
#pragma once  
using namespace System;

namespace MixedCodeCpp
{
    public ref class MyClass
    {
    public:
        HRESULT Something(LPCOLESTR str)
        {
            return S_OK;
        }
    };
}

And here's my code in C# (I've added a reference to the C++ project in the C# project, through Visual Studio):

StringBuilder sb = new StringBuilder();  
sb.Append("Hello world");  
MixedCodeCpp.MyClass cls = new MixedCodeCpp.MyClass();  
cls.Something(sb);
A: 

Try StringBuilder instead of String thusly:

System.Text.StringBuilder test = new System.Text.StringBuilder ();
test.Append("Hello world");
Something(test);

I've used it that way in pinvoke to Win32 functions that required various string pointers as parameters. Not sure it will work with your API but it's worth a shot. Here's some MSDN info about the process. And here is another.

Here's an arbitrary sample of what your import statement and declaration ought to look like. (To be taken with a grain of salt.)

[DllImport(SomeLib.SomeName, CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Something(StringBuilder pMyString);

StringBuilder str = new StringBuilder(MAX_PATH); 
DWORD uSize;

bool b = Something(str);
Paul Sasik
Using your solution, C# throws me the following error: cannot convert from 'System.Text.StringBuilder' to 'char*'. Any ideas? Thank you!
Luís Mendes
@Luis: See the other link i included in the answer too. This should work. There could be a problem with how you're referencing the "Something" function. Could we see that code?
Paul Sasik
Added a rough little code snippet that you could compare.
Paul Sasik
I'm not using DLL import, it's just a C# project referencing a C++ one. That's possible by inserting the two projects in the same solution (Visual Studio), and then adding the reference.
Luís Mendes
Could you put the snippet into your question so that it can be formatted nicely? It's very hard to read in the comments. And you could try using DllImport to see if it works for you.
Paul Sasik
I'm sorry about that, I've put the code in the question. But how can I use DLLImport if I'm just using a simple reference? Thank you
Luís Mendes
+1  A: 

The argument will appear as Char* on the C# side. That requires unsafe code, like this:

    unsafe static void CallSomething(MyClass obj, string arg) {
        IntPtr mem = Marshal.StringToCoTaskMemUni(arg);
        try {
            obj.Something((Char*)mem);
        }
        finally {
            Marshal.FreeCoTaskMem(mem);
        }
    }

It makes very little sense to expose the LPCOLESTR to other managed code. This method really should accept a String^ and convert to wchar_t* internally.

Hans Passant
I'll test your solution, but I agree it's best to convert to wchar_t*. How can I do that? I'm having no success... Thank you!
Luís Mendes
MSDN article: http://msdn.microsoft.com/en-us/library/d1ae6tz5%28VS.80%29.aspx
Hans Passant
Very nice article! Thank you, it solved my problem
Luís Mendes
unsafe?!? That's cheating! ;-) +1
Paul Sasik