Pinvoke question: marshalling pointers to blittable types

  • Thread starter Thread starter Beorne
  • Start date Start date
B

Beorne

I have to call a c++ library funtion with the following signature:
void ReadBool(bool* pb1)
From C# I've imported the function as

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(out bool);

but this does not work, the bool (not initialized) is not correctly
returned.

But when I write

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(ref bool);

All goes well.

It is correct that to marshall poiters it is only correct to use "ref"
and not "out"?

Thanks.
 
it's true. when marshalling pointers you must explicitly use ref (out
is a C# buzzword for ref with checks).

Beorne je napisao/la:
I have to call a c++ library funtion with the following signature:
void ReadBool(bool* pb1)
From C# I've imported the function as

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(out bool);

but this does not work, the bool (not initialized) is not correctly
returned.

But when I write

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(ref bool);

All goes well.

It is correct that to marshall poiters it is only correct to use "ref"
and not "out"?

Thanks.
 
Beorne said:
I have to call a c++ library funtion with the following signature:
void ReadBool(bool* pb1)
From C# I've imported the function as

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(out bool);

but this does not work, the bool (not initialized) is not correctly
returned.

But when I write

[DllImport("library.dll")]
unsafe static extern void NicamPLCRead(ref bool);

All goes well.

It is correct that to marshall poiters it is only correct to use "ref"
and not "out"?

Not really, all depends on the semantics.

If the caller does something like this...
void __stdcall F(bool * b)
{
// set the value of the variable who's address is passed in b to true
*b = true;
}
then you need to call the function like this:

[DllImport("library.dll")]
extern static void F([Out,MarshalAs( UnmanagedType.I1 )] out bool b);
...
F(out b);


If on the other hand, the calle looks like this:
....
bool m_b;
void __stdcall F(bool * b)
{
m_b = false;
// set b to the address of variable m_b
b = &m_b;
}

then you have to call F as:

[DllImport("library.dll")]
extern static void F([In, Out,MarshalAs( UnmanagedType.I1 )] ref bool b);
..
bool b = false;
F(ref b);

Note that when using "bool" in C++, you need to apply the MarshalAs(
UnmanagedType.I1 ) attribute on the bool parameter, failing to do this will
marshal the bool as an int value, which is not what you are expecting in C#.


Willy.
 
bool m_b;
void __stdcall F(bool * b)
{
m_b = false;
// set b to the address of variable m_b
b = &m_b;
}

What do you expect this to accomplish? It overwrites the local copy of the
pointer, passing no data to the caller.

A parameter needing to be passed as ref would be used thusly:

void __stdcall F(bool * pb)
{
*pb++;
}
 
Ben Voigt said:
What do you expect this to accomplish? It overwrites the local copy of
the pointer, passing no data to the caller.

A parameter needing to be passed as ref would be used thusly:

void __stdcall F(bool * pb)
{
*pb++;
}

Oh sure, my bad, forget about this sample.

Willy.
 
Back
Top