Re: Structure Marshalling Question
From: SB (stormfire1_at_yahoo.com)
Date: 02/27/05
- Next message: Senthil: "Conversion of Word Document to PDF format"
- Previous message: Sean Hederman: "Re: Inverse P/Invoke an pointer to pointer"
- In reply to: Thomas Delany: "Re: Structure Marshalling Question"
- Messages sorted by: [ date ] [ thread ]
Date: Sat, 26 Feb 2005 22:02:51 -0500
Have you looked into Marshal::PtrToStringAnsi? I tested the code below and
it worked fine for me. I didn't see a need to create a managed
structure...so I just used the unmanaged one you posted:
typedef struct tag_KVFilterOutput
{
BYTE *pcText;
int cbText;
}KVFilterOutput;
Here is the code in the managed C++ app:
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
KVFilterOutput kvf;
ZeroMemory(&kvf, sizeof(KVFilterOutput)); // just a habit of mine
kvf.cbText = 256;
kvf.pcText = (BYTE *) calloc(kvf.cbText, 1);
if (kvf.pcText != NULL )
{
TestFunc(&kvf); // call the dll function
IntPtr^ p = gcnew IntPtr(kvf.pcText);
System::String^ s =
System::Runtime::InteropServices::Marshal::PtrToStringAnsi(*p, kvf.cbText);
free(kvf.pcText);
}
}
Note that the above is .NET 2.0b code...so the syntax for you will be
slightly different.
Oh...and the DLL code I used to simulate your unmanaged code was something
like:
extern "C" __declspec(dllexport) void TestFunc(KVFilterOutput *data)
{
BYTE buffer[] = {65, 66, 67}; // "ABC" in ANSI
memcpy(data->pcText, buffer, 4);
}
Note that I also set the calling convention in the dll and the application
to _stdcall.
Of course, someone else might point out a better way to do this since I'm
by no means an expert in this area (or in managed C++...since I normally use
C#).
Also, I wondered why you are writing a managed C++ wrapper and using it from
C#...when you can just do it all in C#?
HTH,
-sb
"Thomas Delany" <eshuttle@community.nospam> wrote in message
news:pan.2005.02.26.17.02.04.125000@community.nospam...
> On Fri, 25 Feb 2005 17:34:12 -0500, SB wrote:
>
>> I've been learning about Marshalling structs and handling callbacks all
>> week...so maybe I can help. What do exactly you plan on doing with
>> pcText
>> array? Can you elaborate on what the function does and how you would
>> like
>> to use the results?
>>
>> -sb
>>
>> "Thomas Delany" <eshuttle@community.nospam> wrote in message
>> news:pan.2005.02.25.20.07.55.625000@community.nospam...
>>> Hi,
>>>
>>> I am trying to write a C++ wrapper class using MC++ that wraps calls to
>>> a
>>> dll that exposes a C API.
>>>
>>> I have found several examples of marshalling struct data between managed
>>> and unmanaged code where you have to pass a struct full of data to an
>>> unmanaged code function. I have a slightly different situation that I
>>> am
>>> dealing with, however. I have a C function that requires a pointer to
>>> an
>>> empty struct, which it subsequently fills up with data upon completion.
>>>
>>> Here is the unmanaged struct declaration:
>>>
>>> typedef struct tag_KVFilterOutput
>>> {
>>> BYTE *pcText;
>>> int cbText;
>>> }
>>> KVFilterOutput;
>>>
>>> The unmanaged code sets pcText to the address of a BYTE array containing
>>> the results from the call, and cbText contains the size of the array.
>>> The
>>> caller is responsible for freeing the array.
>>>
>>> I am assuming I will need to create a managed equivalent similar to:
>>>
>>> [StructLayout(LayoutKind::Sequential)]
>>> typedef __value public struct TAG_FilterOutput
>>> {
>>> IntPtr pText;
>>> System::Int32 cbSize;
>>> } FILTER_OUTPUT;
>>>
>>> I believe I know how to code things to pass the empty struct to the
>>> unmanaged function. My question is: how do I marshal the results
>>> pointed
>>> to by pText to something useful in the managed code?
>>>
>>> Thanks in advance.
>>>
>>> Tom Delany
>>>
>
> The API is one we licensed that supports multiple platforms (Windows,
> Linux, Unix, etc.) which is the reason for their implementing the bare
> bones C API (it was the lowest common denominator).
>
> The BYTE array returned by this API function is actually text. I believe
> they declared it as a pointer to a BYTE array because it could potentially
> be in any of several languages, including multi-byte character sets, and
> they felt that BYTE was the best choice due to their LCD approach.
>
> I would be perfectly happy to get this as a String, StringBuilder,
> whatever. I just need to get the results contained in the array into
> something usable from .NET (I intend to call the C++ wrapper from the main
> application, which we are writing in C#).
>
> Thanks,
>
> Tom Delany
>
- Next message: Senthil: "Conversion of Word Document to PDF format"
- Previous message: Sean Hederman: "Re: Inverse P/Invoke an pointer to pointer"
- In reply to: Thomas Delany: "Re: Structure Marshalling Question"
- Messages sorted by: [ date ] [ thread ]