pinvoking with pointers

  • Thread starter Thread starter Peter Hartlén
  • Start date Start date
P

Peter Hartlén

Hi!

I've read a couple of threads on this subject but I still don't understand
this simple problem:

I have a C++ dll which exports a function with the following structure:

int GetVersion( StError *err, StVersion *ver);

StError is defined as
struct StError
int iError;

StVersion is defined as:
struct StVersion
char chVersion[16];
int iBuildNumber;

How would I use this in C#?

This is what I first thought to use the followin dllimport definition:
short GetVersion( ref IntPtr err, ref IntPtr ver)

int GetVersion()
{
IntPtr err, ver;
GetVersion( ref err, ref ver);

// How do I reference the actual data of the pointer???
// The C++ equivalent would be something like err->iError (If I'm not
remembering wrong)
if( (int)err == 0 )
{
label1.Text = ver ... ???
}
}

Perhaps the version struct is too complicated to be able to use ordinary
marshalling in CF, but the Error struct shouldn't be, right? So the question
is twofold, how do I reference a pointer argument to retrieve it's data, and
how complicated can the structures be if it is possible to do this way??

/ Peter
 
When you receive a valid pointer you will can copy the underlying structure
into byte array and then read it with BitConverter.
 
Hello Alex and thanks for your reply!

Ok, I see what you are saying and I am using your AdvancedMarshaler in hope
of making it easier for me. At this point I am however trying to understand
how I should declare my C# functions, and how to call the C++-exported
function.

Given C++-declaration:
would the correct C# be:

(DLLImport)
short GetVersion( ref IntPtr pErr, ref IntPtr pVer)

public short MyVersion(...)
{
IntPtr pErr = IntPtr.Zero;
IntPtr pVer = IntPtr.Zero;
short shRes;
shRes = GetVersion(ref pErr, ref pVer); <--- Here he application crash
without any exception beeing thrown/catched...

.... code to handle the structures etc..

}


.... Other ideas ...
As I am using your AdvancedMarshaler I was considering usig ref byte[] pVer
in the dllimport-declaration, but then I would have some trouble setting the
argument in the function call.

My class inheriting from AdvancedMarshaler looks like this:

public class StVersion: AdvancedMarshaler
{
[CustomMarshalAs(SizeConst = 16)]
public string szVersion;
public short shBuildNumber;

public StVersion()
{
this.data = new byte[this.GetSize()];
}

public StVersion(int size)
{
this.data = new byte[size];
}
}

The problem is that I can't do this: GetVersion( ref stVer.ByteArray, ... )
(as you would do GetVersion( stVer.ByteArray) if the argument was a plain
StVersion struct...

To be honest, I'm not even sure ref is the right thing to use for a C++
*-argument...

/ Peter on deep water



Alex Yakhnin said:
When you receive a valid pointer you will can copy the underlying
structure
into byte array and then read it with BitConverter.

--
--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Peter Hartlén said:
Hi!

I've read a couple of threads on this subject but I still don't
understand
this simple problem:

I have a C++ dll which exports a function with the following structure:

int GetVersion( StError *err, StVersion *ver);

StError is defined as
struct StError
int iError;

StVersion is defined as:
struct StVersion
char chVersion[16];
int iBuildNumber;

How would I use this in C#?

This is what I first thought to use the followin dllimport definition:
short GetVersion( ref IntPtr err, ref IntPtr ver)

int GetVersion()
{
IntPtr err, ver;
GetVersion( ref err, ref ver);

// How do I reference the actual data of the pointer???
// The C++ equivalent would be something like err->iError (If I'm not
remembering wrong)
if( (int)err == 0 )
{
label1.Text = ver ... ???
}
}

Perhaps the version struct is too complicated to be able to use ordinary
marshalling in CF, but the Error struct shouldn't be, right? So the
question
is twofold, how do I reference a pointer argument to retrieve it's data,
and
how complicated can the structures be if it is possible to do this way??

/ Peter
 
Try to use just IntPtr without ref.

--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Peter Hartlén said:
Hello Alex and thanks for your reply!

Ok, I see what you are saying and I am using your AdvancedMarshaler in hope
of making it easier for me. At this point I am however trying to understand
how I should declare my C# functions, and how to call the C++-exported
function.

Given C++-declaration:
would the correct C# be:

(DLLImport)
short GetVersion( ref IntPtr pErr, ref IntPtr pVer)

public short MyVersion(...)
{
IntPtr pErr = IntPtr.Zero;
IntPtr pVer = IntPtr.Zero;
short shRes;
shRes = GetVersion(ref pErr, ref pVer); <--- Here he application crash
without any exception beeing thrown/catched...

.... code to handle the structures etc..

}


.... Other ideas ...
As I am using your AdvancedMarshaler I was considering usig ref byte[] pVer
in the dllimport-declaration, but then I would have some trouble setting the
argument in the function call.

My class inheriting from AdvancedMarshaler looks like this:

public class StVersion: AdvancedMarshaler
{
[CustomMarshalAs(SizeConst = 16)]
public string szVersion;
public short shBuildNumber;

public StVersion()
{
this.data = new byte[this.GetSize()];
}

public StVersion(int size)
{
this.data = new byte[size];
}
}

The problem is that I can't do this: GetVersion( ref stVer.ByteArray, ... )
(as you would do GetVersion( stVer.ByteArray) if the argument was a plain
StVersion struct...

To be honest, I'm not even sure ref is the right thing to use for a C++
*-argument...

/ Peter on deep water



Alex Yakhnin said:
When you receive a valid pointer you will can copy the underlying
structure
into byte array and then read it with BitConverter.

--
--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Peter Hartlén said:
Hi!

I've read a couple of threads on this subject but I still don't
understand
this simple problem:

I have a C++ dll which exports a function with the following structure:

int GetVersion( StError *err, StVersion *ver);

StError is defined as
struct StError
int iError;

StVersion is defined as:
struct StVersion
char chVersion[16];
int iBuildNumber;

How would I use this in C#?

This is what I first thought to use the followin dllimport definition:
short GetVersion( ref IntPtr err, ref IntPtr ver)

int GetVersion()
{
IntPtr err, ver;
GetVersion( ref err, ref ver);

// How do I reference the actual data of the pointer???
// The C++ equivalent would be something like err->iError (If I'm not
remembering wrong)
if( (int)err == 0 )
{
label1.Text = ver ... ???
}
}

Perhaps the version struct is too complicated to be able to use ordinary
marshalling in CF, but the Error struct shouldn't be, right? So the
question
is twofold, how do I reference a pointer argument to retrieve it's data,
and
how complicated can the structures be if it is possible to do this way??

/ Peter
 
Tried it but it's giving the same result (crash without any managed
exception beeing thrown).

I'm able to do a void function call (i.e. BringToFront() ) so the actual
DLLImports should be ok...

I'm calling it for today, will have a look at it tomorrow...

Thanks for trying to help me!

/ Peter



Alex Yakhnin said:
Try to use just IntPtr without ref.

--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Peter Hartlén said:
Hello Alex and thanks for your reply!

Ok, I see what you are saying and I am using your AdvancedMarshaler in
hope
of making it easier for me. At this point I am however trying to
understand
how I should declare my C# functions, and how to call the C++-exported
function.

Given C++-declaration:
int GetVersion( StError *err, StVersion *ver);

would the correct C# be:

(DLLImport)
short GetVersion( ref IntPtr pErr, ref IntPtr pVer)

public short MyVersion(...)
{
IntPtr pErr = IntPtr.Zero;
IntPtr pVer = IntPtr.Zero;
short shRes;
shRes = GetVersion(ref pErr, ref pVer); <--- Here he application crash
without any exception beeing thrown/catched...

.... code to handle the structures etc..

}


.... Other ideas ...
As I am using your AdvancedMarshaler I was considering usig ref byte[]
pVer
in the dllimport-declaration, but then I would have some trouble setting
the
argument in the function call.

My class inheriting from AdvancedMarshaler looks like this:

public class StVersion: AdvancedMarshaler
{
[CustomMarshalAs(SizeConst = 16)]
public string szVersion;
public short shBuildNumber;

public StVersion()
{
this.data = new byte[this.GetSize()];
}

public StVersion(int size)
{
this.data = new byte[size];
}
}

The problem is that I can't do this: GetVersion( ref stVer.ByteArray,
... )
(as you would do GetVersion( stVer.ByteArray) if the argument was a plain
StVersion struct...

To be honest, I'm not even sure ref is the right thing to use for a C++
*-argument...

/ Peter on deep water



Alex Yakhnin said:
When you receive a valid pointer you will can copy the underlying
structure
into byte array and then read it with BitConverter.

--
--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


:

Hi!

I've read a couple of threads on this subject but I still don't
understand
this simple problem:

I have a C++ dll which exports a function with the following
structure:

int GetVersion( StError *err, StVersion *ver);

StError is defined as
struct StError
int iError;

StVersion is defined as:
struct StVersion
char chVersion[16];
int iBuildNumber;

How would I use this in C#?

This is what I first thought to use the followin dllimport definition:
short GetVersion( ref IntPtr err, ref IntPtr ver)

int GetVersion()
{
IntPtr err, ver;
GetVersion( ref err, ref ver);

// How do I reference the actual data of the pointer???
// The C++ equivalent would be something like err->iError (If I'm
not
remembering wrong)
if( (int)err == 0 )
{
label1.Text = ver ... ???
}
}

Perhaps the version struct is too complicated to be able to use
ordinary
marshalling in CF, but the Error struct shouldn't be, right? So the
question
is twofold, how do I reference a pointer argument to retrieve it's
data,
and
how complicated can the structures be if it is possible to do this
way??

/ Peter
 
How do you debug when there's a crash with the white screen saying something
like (direct translation) "A native exception has been thrown in
MyApp.exe..." I press Info and I get the follwing error information:

Exception code: 0xc0000005
Exception address: 0x0101884f0
Writes: 0x28000000

What does this mean? We are trying write the value 28?? to the address
0x0101884f0, and the exception code 0xc0000005 was thrown, which I think
means invalid address?!? So the problem comes down to that the API function
isn't able to write to the memory I create for it, right?

I'm now just trying to get a much simpler function to work, it's:
INT StartApplication( TError *aError);

C++ definition of the struct:
struct TError
{ int iError; }

the equal to this in C# would be
class TError // class or struct shouldn't matter but as we are using
references I thought this is the best
{ public Int16 iError; }

Here are my desperate attempts:

1. StartApplication( IntPtr pErrror )

IntPtr p = IntPtr.Zero
StartApplication( p );

This is not working, and I feel I need to create the memory block the
pointer points to before I send it to the dll, so I tried:

2. Same as 1 but using LocalAlloc.
IntPtr p = LocalAlloc( 0, 2)
// Also tried LocalAlloc(0,4) but the TError C++ struct is 2 bytes large,
right?
StartApplication( p );
// Do some conversion of p
FreeAlloc(p);

Still not working...

3. StartApplicaton( ref TError pErrror )
using the declaration of TError above

TError err = new TError();
StartApplication( ref err );

Still not working...

4. StartApplication( ref byte[] pErrror )

byte[] arrErr = new byte[2]; // This is a simplified version of Alex
Yakhnin's method of sending byte streams
StartApplication( ref arrErr );

Not working...


The water is getting deeper...


Alex Yakhnin said:
Try to use just IntPtr without ref.

--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Peter Hartlén said:
Hello Alex and thanks for your reply!

Ok, I see what you are saying and I am using your AdvancedMarshaler in
hope
of making it easier for me. At this point I am however trying to
understand
how I should declare my C# functions, and how to call the C++-exported
function.

Given C++-declaration:
int GetVersion( StError *err, StVersion *ver);

would the correct C# be:

(DLLImport)
short GetVersion( ref IntPtr pErr, ref IntPtr pVer)

public short MyVersion(...)
{
IntPtr pErr = IntPtr.Zero;
IntPtr pVer = IntPtr.Zero;
short shRes;
shRes = GetVersion(ref pErr, ref pVer); <--- Here he application crash
without any exception beeing thrown/catched...

.... code to handle the structures etc..

}


.... Other ideas ...
As I am using your AdvancedMarshaler I was considering usig ref byte[]
pVer
in the dllimport-declaration, but then I would have some trouble setting
the
argument in the function call.

My class inheriting from AdvancedMarshaler looks like this:

public class StVersion: AdvancedMarshaler
{
[CustomMarshalAs(SizeConst = 16)]
public string szVersion;
public short shBuildNumber;

public StVersion()
{
this.data = new byte[this.GetSize()];
}

public StVersion(int size)
{
this.data = new byte[size];
}
}

The problem is that I can't do this: GetVersion( ref stVer.ByteArray,
... )
(as you would do GetVersion( stVer.ByteArray) if the argument was a
plain
StVersion struct...

To be honest, I'm not even sure ref is the right thing to use for a C++
*-argument...

/ Peter on deep water



"Alex Yakhnin [MVP]" <[email protected]> skrev i meddelandet
When you receive a valid pointer you will can copy the underlying
structure
into byte array and then read it with BitConverter.

--
--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


:

Hi!

I've read a couple of threads on this subject but I still don't
understand
this simple problem:

I have a C++ dll which exports a function with the following
structure:

int GetVersion( StError *err, StVersion *ver);

StError is defined as
struct StError
int iError;

StVersion is defined as:
struct StVersion
char chVersion[16];
int iBuildNumber;

How would I use this in C#?

This is what I first thought to use the followin dllimport
definition:
short GetVersion( ref IntPtr err, ref IntPtr ver)

int GetVersion()
{
IntPtr err, ver;
GetVersion( ref err, ref ver);

// How do I reference the actual data of the pointer???
// The C++ equivalent would be something like err->iError (If I'm
not
remembering wrong)
if( (int)err == 0 )
{
label1.Text = ver ... ???
}
}

Perhaps the version struct is too complicated to be able to use
ordinary
marshalling in CF, but the Error struct shouldn't be, right? So the
question
is twofold, how do I reference a pointer argument to retrieve it's
data,
and
how complicated can the structures be if it is possible to do this
way??

/ Peter
 
Back
Top