Pinvoke question: marshalling pointers to blittable types

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.
 
M

Miroslav Stampar [MCSD.NET / Security+]

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.
 
W

Willy Denoyette [MVP]

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.
 
B

Ben Voigt [C++ MVP]

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++;
}
 
W

Willy Denoyette [MVP]

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top