6

I want to make a native C++ all that can be used from a C# project.

  • If I want to pass a string from C# to the function in the C++ all, what parameter should I use?
  • I know that C# strings use Unicode, so I tried wchar_t * for the function but it didn't work; I tried catching any exceptions raised from the called function, but no exception was thrown.
  • I also want to return a string so I can test it.

The C++ function is the following:

DECLDIR wchar_t * setText(wchar_t * allText) {
  return allText;
}

The C# code is the following:

[DllImport("firstDLL.Dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]     
public static extern string setText(string allText);

var allText= new string('c',4);
try {
  var str1 = setText(allText);
}
catch (Exception ex) {
  var str2 = ex.Message;
}

What type should I use for the C++ function's return type, so that I can call it from C# with a return type of string[]? the same Q but for the parameter of the function to be string[] in C#?

apaderno
  • 28,547
  • 16
  • 75
  • 90
ghet
  • 145
  • 1
  • 4
  • 1
    By the way, use of var like this will soon come back to bite you when you find you have no idea what type any of your variables are. – David Heffernan Mar 20 '11 at 13:27
  • As soon as you compile these 3 var(s) become string. – ukhardy Mar 20 '11 at 13:34
  • 2
    @ukhardy oh come on, I know that! The point is that when you have var scattered all over your code, and it's more complex than this, you find it becomes a hindrance to understanding existing code. – David Heffernan Mar 20 '11 at 13:56
  • +1.. thats's true David. – ukhardy Mar 20 '11 at 14:29
  • 1
    @David - Since var's are locally scoped, this would only really be a problem if the functions are huge, in which case one may have other problems and need to consider refactoring. I've found the only time I'm even mildly confused by var is when I'm viewing a file in a source control tool and don't have intellisense readily available – Steve Mar 20 '11 at 14:35

3 Answers3

3

I'd probably do it with a COM BSTR and avoid having to mess with buffer allocation. Something like this:

C++

#include <comutil.h>
DECLDIR BSTR * setText(wchar_t * allText)
{
    return ::SysAllocString(allText);
}

C#

[DllImport(@"firstDLL.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string setText(string allText);

BSTR is the native COM string type. The advantage of using it here is that the memory can be allocated on the native side of the interface (in C++) with the COM allocator, and then destroyed on the managed side of the interface with the same allocator. The P/Invoke marshaller knows all about BSTR and handles everything for you.

Whilst you can solve this problem by passing around buffer lengths, it results in rather messy code, which is why I have a preference for BSTR.


For your second question, about P/Invoking string[], I think you'll find what you need from Chris Taylor's answer to another question here on Stack Overflow.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I realy need to be able to hadle any char that microsoft word can use so the Q is : Can BSTR hold unicode char? – ghet Mar 20 '11 at 13:52
  • @ghet BSTR only holds Unicode char! It's perfect for your needs in my opinion. – David Heffernan Mar 20 '11 at 13:55
  • as for the second Q : what to use in C++ for the return type so that I can have a string[] return type in c# , can you help with that? – ghet Mar 20 '11 at 13:57
  • @ghet string[] takes you to marshalling arrays. But I think it's a bit unfair of you to ask two questions in one! – David Heffernan Mar 20 '11 at 14:00
  • @ghet By this I mean that the second question tacked on right at the end is quite different and really deserves to be a question in its own right. It's no doubt been covered here many times already. In order to answer it we would need to know more. Fundamentally we'd want to know which bit of code decides how many elements are in the array. – David Heffernan Mar 20 '11 at 14:09
  • @ghet I've updated my answer with a link to another SO question that will deal with the string[] part of your problem. I think I've got it all covered now!! – David Heffernan Mar 20 '11 at 14:23
  • @ukhardy "Binary String" I didn't even know that was what BSTR stood for! Apparently it could also be "Basic String". – David Heffernan Mar 20 '11 at 14:38
1

A very useful site with tooling and lots of good information is http://pinvoke.net/

It might help you.

Emond
  • 50,210
  • 11
  • 84
  • 115
0

C++

void GetString( char* buffer, int* bufferSize ); 

C#

int bufferSize = 512; 
StringBuilder buffer = new StringBuilder( bufferSize ); 
GetString( buffer, ref bufferSize )
ukhardy
  • 2,084
  • 1
  • 13
  • 12