469,583 Members | 2,590 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,583 developers. It's quick & easy.

Return string from c++ dll - interop services

Hi,

I am having some trouble returning a string from a c++ dll. I tend to get
junk data back and I am not sure of the method, my code so far:

Function is declared in c++ dll 'Test' and exported like this:

extern "C" __declspec( dllexport ) BSTR getbagstr();
extern "C" __declspec( dllexport ) BSTR getbagstr() {
g.getbag()->setdisplaybag("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
const char * buff = g.getbag()->getdisplaybag().c_str();
return SysAllocStringByteLen (buff , lstrlen(buff));
}

I want use the function via interop services - p/invoke - to display the
string in a simple c# program:

[DllImport("Test")]
private static extern IntPtr getbagstr();

public static string getBagString()
{
return Marshal.PtrToStringAuto(getbagstr());
}

The data I am returning is not correct. All display bag does is store and
return the string as below. I am returning int data correctly, but strings
are proving difficult. Anybody able to help?

void Bag::setdisplaybag(const string & str) {
displaybag = str;
}

string Bag::getdisplaybag() { return displaybag; }

Sep 3 '06 #1
5 8949
public static string getBagString()
{
return Marshal.PtrToStringAuto(getbagstr());
}
SysAllocStringByteLen returns a BSTR containing ANSI characters. So
PtrToStringAuto will only work on Win9x platforms. Try changing it to

IntPtr ptr = getbagstr();
string tmp = Marshal.PtrToStringAnsi(ptr);
Marshal.FreeBSTR(ptr);
return s;
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Sep 3 '06 #2
On Sun, 03 Sep 2006 23:21:35 +0200, Mattias Sjögren wrote:
> public static string getBagString()
{
return Marshal.PtrToStringAuto(getbagstr());
}

SysAllocStringByteLen returns a BSTR containing ANSI characters. So
PtrToStringAuto will only work on Win9x platforms. Try changing it to

IntPtr ptr = getbagstr();
string tmp = Marshal.PtrToStringAnsi(ptr);
Marshal.FreeBSTR(ptr);
return s;
Thanks Mattias, this worked. I have been checking through the p/invoke
examples on your website which is an excellent resource. However, I
wondered if you could provide an example for this code:

extern "C" __declspec( dllexport ) __stdcall void setdisplaybag(LPSTR
tiles);
extern "C" __declspec( dllexport ) __stdcall void setdisplaybag(LPSTR
tiles) {
//set display bag code
}

Assuming the above is the exported c++ function, how should C# pass in the
BSTR safely? How should the BSTR be freed or should it?

[DllImport("Test")]
private static extern void setdisplaybag(IntPtr ptr);

public static void SetDisplayBag(string str)
{
IntPtr tmp = Marshal.StringToBSTR(str);
setdisplaybag(tmp);
//Marshal.FreeBSTR(tmp);
}
Sep 3 '06 #3
>Assuming the above is the exported c++ function, how should C# pass in the
>BSTR safely?
I see nothing about BSTRs in the function signatures, so I would
simply declare it as

static extern void setdisplaybag(string tiles);

Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Sep 4 '06 #4
On Tue, 05 Sep 2006 00:05:07 +0200, Mattias Sjögren wrote:
I see nothing about BSTRs in the function signatures, so I would
simply declare it as

static extern void setdisplaybag(string tiles);
Ok fine, but when I input this i get strange output:

settiles("ZZZZZZZZZYYYYYYYYYYYYYY");
Console.WriteLine(getbagstr());

console output:

v►☺YYYYYYYYYYYYYZZZZZZZZZ

Where are the extra characters coming from at the beginning and what is
needed to avoid them? Thanks in advance.
Sep 5 '06 #5
Jason,
>Where are the extra characters coming from at the beginning and what is
needed to avoid them? Thanks in advance.
I don't know without seeing all the C++ code. It doesn't happen here.
I wrote the folowing test code and it roundtrips the string correctly.

// C++ DLL
#include <windows.h>
#pragma comment(lib, "oleaut32.lib")

char buf[100];

extern "C"
{
__declspec(dllexport) BSTR __stdcall getbagstr()
{
return SysAllocStringByteLen(buf, lstrlen(buf));
}

__declspec(dllexport) void __stdcall setdisplaybag(char *tiles)
{
lstrcpyn(buf, tiles, 100);
}

}

// C# client
using System;
using System.Runtime.InteropServices;

class Test
{
[DllImport("test.dll")]
static extern IntPtr getbagstr();

[DllImport("test.dll")]
static extern void setdisplaybag(string tiles);

static void Main()
{
setdisplaybag("ZZZZZZZZZYYYYYYYYYYYYYY");
IntPtr p = getbagstr();
Console.WriteLine(Marshal.PtrToStringAnsi(p));
Marshal.FreeBSTR(p);
}
}
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Sep 7 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Tom Leylan | last post: by
6 posts views Thread by Bruce W.1 | last post: by
10 posts views Thread by Mark Jerde | last post: by
1 post views Thread by Bart Roozendaal | last post: by
reply views Thread by suresh191 | last post: by
4 posts views Thread by guiromero | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.