473,847 Members | 1,845 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 11783
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(vo id)
{
return ppp;
}

method #1:

using System;
using System.Runtime. InteropServices ;

class MainClass
{

[DllImport("D:\\ IDEProjects\\Vi sualStudio\\Ptr PtrPtr\\Release \\PtrPtrPtr.dll ")]
private static extern IntPtr ptrptrptr();
public static void Main(string[] args)
{
IntPtr ppp = ptrptrptr();
IntPtr pp1 = Marshal.ReadInt Ptr(ppp, 0);
IntPtr pp2 = Marshal.ReadInt Ptr(ppp, 4);
IntPtr p1 = Marshal.ReadInt Ptr(pp1, 0);
IntPtr p2 = Marshal.ReadInt Ptr(pp1, 4);
IntPtr p3 = Marshal.ReadInt Ptr(pp1, 8);
IntPtr p4 = Marshal.ReadInt Ptr(pp2, 0);
IntPtr p5 = Marshal.ReadInt Ptr(pp2, 4);
IntPtr p6 = Marshal.ReadInt Ptr(pp2, 8);
string s1 = Marshal.PtrToSt ringAnsi(p1);
string s2 = Marshal.PtrToSt ringAnsi(p2);
string s3 = Marshal.PtrToSt ringAnsi(p3);
string s4 = Marshal.PtrToSt ringAnsi(p4);
string s5 = Marshal.PtrToSt ringAnsi(p5);
string s6 = Marshal.PtrToSt ringAnsi(p6);
Console.WriteLi ne(s1 + " " + s2 + " " + s3 + " " + s4 + " " +
s5 + " " + s6);
}
}

method #2:

using System;
using System.Runtime. InteropServices ;

class MainClass
{

[DllImport("D:\\ IDEProjects\\Vi sualStudio\\Ptr PtrPtr\\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.ReadInt Ptr(ppp, 4*i);
for(int j = 0; j < 3; j++)
{
IntPtr p = Marshal.ReadInt Ptr(pp, 4*j);
string s = Marshal.PtrToSt ringAnsi(p);
Console.WriteLi ne(s);
}
}
}
}

method #3:

using System;
using System.Runtime. InteropServices ;

class MainClass
{

[DllImport("D:\\ IDEProjects\\Vi sualStudio\\Ptr PtrPtr\\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.ReadInt Ptr(ppp, 4*i);
for(int j = 0; j < 3; j++)
{
IntPtr p = Marshal.ReadInt Ptr(pp, 4*j);
for(int k = 0; k < (3*i+j+1); k++)
{
byte b = Marshal.ReadByt e(p, k);
Console.Write(( char)b);
}
Console.WriteLi ne();
}
}
}
}

method #4:

using System;
using System.Runtime. InteropServices ;

unsafe class MainClass
{

[DllImport("D:\\ IDEProjects\\Vi sualStudio\\Ptr PtrPtr\\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.WriteLi ne();
}
}
}
}

Arne

Oct 26 '06 #2
On 25 Oct 2006 13:31:49 -0700, "DG is a god...."
<ri************ ****@hotmail.co mwrote:
>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 MultiByteToWide Chars Win32 API).

Mr.Asm
Oct 27 '06 #3
On Fri, 27 Oct 2006 07:50:04 GMT, MrAsm <in*****@invali d.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
2327
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
1483
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 or just void. for some reason, this one is returning a string (char *) or in other interfaces is returning a struct. i'm pretty familiar with interop for normal params and using IntPtr marshalling to structures, but i'm not sure how this works...
4
3408
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 HEX value of 4E 31 00 00 01 00 20 20 20 20 20 00 00 00 20 20 20 31 32 30. But when it gets back to Vb.net all I have is 4E 31 or N1. Now I can return the same string as a return value of a function and I get it all. Please Help, Patrick Horn...
6
13429
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 very little luck processing the Hashtable itself in VB6 (I can add a reference to the project so it knows what a Hashtable is, but I'm not having much luck looping through all objects in the Hashtable), so I decided to try a different idea.
5
2146
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 recognize that the created array is the same as the declared interface argument. The C# function is expecting to receive a 2 dimensioned array and is declared like this: public object InteropFunc( string s1, object arValues ); What should the ASP...
5
9525
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 exported like this: extern "C" __declspec( dllexport ) BSTR getbagstr(); extern "C" __declspec( dllexport ) BSTR getbagstr() { g.getbag()->setdisplaybag("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
5
3121
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 = g.getbag()->getbagstr(true).c_str(); return buff; } VS 2005, C# declaration
0
1651
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 function) needs to allocate the buffer and return it as an out param to the "C" dll. When invoking the callback from the C code, passing a valid pointer with sizeParam=0 cause the application to crash - I can't even enter the callback scope....
8
13774
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 wrapper layers in unmanaged C++ and C#. I've thought about two approaches: 1) To pass a StringBuilder, this is converted to a char* in C++, the wrapper code converts the char* to a std::string (copy), and in the
0
10982
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10645
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10706
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10331
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9480
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7880
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7053
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5909
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
3160
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.