472,958 Members | 2,342 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

C++ / C# Interop - Returning a char **

Dear All
,
This is my first post - please go easy...!

I have a DLL written in C++ that has the following function exported
from it -:

char** ListHandles(int *processID);

The processID parameter is used to find all associated open file
handles , this value is then written to to return the number of strings
returned in the char**. The return value is an array of strings
listing a set of file handles. I have written a harness in C++ to test
the DLL and it works well in C++...

My task is to now use this DLL in C#.

I have yet to find ANY documentation on how to pass the char ** into a
C# application.

I have the following two requests -:

1. What should the interop definition be to return the char** into C#

2. How do I then extra the strings from the C# type? Are there any
pre-requisites in C++ (ie should the strings be Uni Code?)

I look forward to any response

Richard

Oct 25 '06 #1
3 11585
DG is a god.... wrote:
I have a DLL written in C++ that has the following function exported
from it -:

char** ListHandles(int *processID);

The processID parameter is used to find all associated open file
handles , this value is then written to to return the number of strings
returned in the char**. The return value is an array of strings
listing a set of file handles. I have written a harness in C++ to test
the DLL and it works well in C++...

My task is to now use this DLL in C#.

I have yet to find ANY documentation on how to pass the char ** into a
C# application.
I don't have an example for char** - can you use one for char*** ?

:-)

The following code is not intended for anything else than showing
how to use ReadIntPtr and unsafe.

C++ code:

....

char *p1 = "A";
char *p2 = "BB";
char *p3 = "CCC";
char *p4 = "DDDD";
char *p5 = "EEEEE";
char *p6 = "FFFFFF";
char *pp1[] = { p1, p2, p3 };
char *pp2[] = { p4, p5, p6 };
char **ppp[] = { pp1, pp2 };

PTRPTRPTR_API char ***ptrptrptr(void)
{
return ppp;
}

method #1:

using System;
using System.Runtime.InteropServices;

class MainClass
{

[DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPt r\\Release\\PtrPtrPtr.dll")]
private static extern IntPtr ptrptrptr();
public static void Main(string[] args)
{
IntPtr ppp = ptrptrptr();
IntPtr pp1 = Marshal.ReadIntPtr(ppp, 0);
IntPtr pp2 = Marshal.ReadIntPtr(ppp, 4);
IntPtr p1 = Marshal.ReadIntPtr(pp1, 0);
IntPtr p2 = Marshal.ReadIntPtr(pp1, 4);
IntPtr p3 = Marshal.ReadIntPtr(pp1, 8);
IntPtr p4 = Marshal.ReadIntPtr(pp2, 0);
IntPtr p5 = Marshal.ReadIntPtr(pp2, 4);
IntPtr p6 = Marshal.ReadIntPtr(pp2, 8);
string s1 = Marshal.PtrToStringAnsi(p1);
string s2 = Marshal.PtrToStringAnsi(p2);
string s3 = Marshal.PtrToStringAnsi(p3);
string s4 = Marshal.PtrToStringAnsi(p4);
string s5 = Marshal.PtrToStringAnsi(p5);
string s6 = Marshal.PtrToStringAnsi(p6);
Console.WriteLine(s1 + " " + s2 + " " + s3 + " " + s4 + " " +
s5 + " " + s6);
}
}

method #2:

using System;
using System.Runtime.InteropServices;

class MainClass
{

[DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPt r\\Release\\PtrPtrPtr.dll")]
private static extern IntPtr ptrptrptr();
public static void Main(string[] args)
{
IntPtr ppp = ptrptrptr();
for(int i = 0; i < 2; i++)
{
IntPtr pp = Marshal.ReadIntPtr(ppp, 4*i);
for(int j = 0; j < 3; j++)
{
IntPtr p = Marshal.ReadIntPtr(pp, 4*j);
string s = Marshal.PtrToStringAnsi(p);
Console.WriteLine(s);
}
}
}
}

method #3:

using System;
using System.Runtime.InteropServices;

class MainClass
{

[DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPt r\\Release\\PtrPtrPtr.dll")]
private static extern IntPtr ptrptrptr();
public static void Main(string[] args)
{
IntPtr ppp = ptrptrptr();
for(int i = 0; i < 2; i++)
{
IntPtr pp = Marshal.ReadIntPtr(ppp, 4*i);
for(int j = 0; j < 3; j++)
{
IntPtr p = Marshal.ReadIntPtr(pp, 4*j);
for(int k = 0; k < (3*i+j+1); k++)
{
byte b = Marshal.ReadByte(p, k);
Console.Write((char)b);
}
Console.WriteLine();
}
}
}
}

method #4:

using System;
using System.Runtime.InteropServices;

unsafe class MainClass
{

[DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPt r\\Release\\PtrPtrPtr.dll")]
private static extern byte ***ptrptrptr();
public static void Main(string[] args)
{
byte ***ppp = ptrptrptr();
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 3; j++)
{
for(int k = 0; k < (3*i+j+1); k++)
{
Console.Write((char)ppp[i][j][k]);
}
Console.WriteLine();
}
}
}
}

Arne

Oct 26 '06 #2
On 25 Oct 2006 13:31:49 -0700, "DG is a god...."
<ri****************@hotmail.comwrote:
>Dear All
,
This is my first post - please go easy...!
Don't warry. Also me I'm new in the newsgroup :)
>I have a DLL written in C++ that has the following function exported
from it -:

char** ListHandles(int *processID);

The processID parameter is used to find all associated open file
handles , this value is then written to to return the number of strings
returned in the char**. The return value is an array of strings
listing a set of file handles.
I'm absolutely not a C# expert.
But I think your function prototype hides a problem.
i.e. I suppose that your strings are dynamically allocated on the heap
by your C++ code, right? For example, you use new char[len+1].
So, to avoid memory leaks, you should clear the dynamic strings from
the heap.

If you allocate string buffer with new[], you should use delete[].
If you allocate string buffer with malloc(), you should use free().

I don't know if the C# run-time could know what allocation method you
used, and so do proper cleanup. I think it cannot.

If I were passed string arrays from C++ to Visual Basic 6, I would use
SAFEARRAY of BSTRs. BSTRs are COM strings (Unicode null-terminated
strings, with the character count preceding the first string
character), allocated in C++ using SysAllocString.
So the run-time of the caller (Visual Basic, C#...) should be able to
correctly free them using SysFreeString() internally (I suppose).

So, my suggestion to you is to write C++ code to pack your "char **"
into a more safe and robust data-structure: a SAFEARRAY of BSTRs, and
pass it to C#. I think the C# run-time could be able to correctly
manage it, like Visual Basic 6 runtime does.

BTW: BSTRs are Unicode (UTF16, i.e. 16 bits chars or wchar_t) strings,
so if your string are ANSI, you should convert them to Unicode first
(e.g. use MultiByteToWideChars Win32 API).

Mr.Asm
Oct 27 '06 #3
On Fri, 27 Oct 2006 07:50:04 GMT, MrAsm <in*****@invalid.comwrote:
>So, my suggestion to you is to write C++ code to pack your "char **"
into a more safe and robust data-structure: a SAFEARRAY of BSTRs, and
pass it to C#. I think the C# run-time could be able to correctly
manage it, like Visual Basic 6 runtime does.
Moreover, if you want to make your life easier, and ignore the
SAFEARRAY of BSTR construction, you could do the following:

1. Write a C++ code that wraps your DLL function, and that packs all
the string returned by your DLL function into a single big string.
The sub-strings can be separated using some character (e.g. space).

2. You pass this big string from C++ to C#, e.g using BSTR

3. Write C# code to unpack the big string into the sub-strings (I'm
sure C# has library code to do this with simple method calls).

Another alternative could be to use managed C++ to transfer your
string array to C#.
Oct 27 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Interop newbie | last post by:
Hello, The following code makes an interop call to a Com object from C#: //Create a Bom object NewsBusObjsRCW.NewsBomObjClass myNewsBom = new NewsBusObjsRCW.NewsBomObjClass();
2
by: Kirk Marple | last post by:
i'm attempting to interop from C# to a COM DLL, and have found some trouble with a non-standard interface (at bottom of post - followed by my C# version). typically COM methods return an HRESULT...
4
by: DotNetJunkies User | last post by:
I am calling a VB6 dll from a vb.net windows application that returns an array of strings. My issue is it seems to truncate after a NULL character. For Example VB 6 is returning a string with the...
6
by: Scott M. Lyon | last post by:
As I mentioned in my other post, I'm attempting to, using COM Interop so I can update existing VB6 code to (for several specific functions) return a Hashtable from a .NET library. I've had...
5
by: Richard Lewis Haggard | last post by:
I am trying to create multi-dimensioned arrays in conventional ASP pages and pass these arrays as arguments to functions that are in a C# interop assembly. ASP complains because it doesn't...
5
by: Jason | last post by:
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...
5
by: Jason | last post by:
I am trying to retrieve string data from a c++ dll: extern "C" __declspec( dllexport ) const char * getbagstr(); extern "C" __declspec( dllexport ) const char * getbagstr() { const char * buff...
0
by: Udi | last post by:
Hi all, I'm having difficulties returning a buffer allocated on a callback called from a native dll to .NET assembly. (See pseudo code below in "Foo" func): The managed assembly (the called back...
8
by: Edson Manoel | last post by:
I have some C++ unmanaged code that takes std::string& arguments (as reference), and fills them (possibly growing the string). I want to call this code through PInvoke (DllImport), possibly using...
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.