473,394 Members | 1,800 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 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 11731
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.