By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,836 Members | 2,059 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,836 IT Pros & Developers. It's quick & easy.

Unmanaged C++ Dll / C# bool return problem

P: n/a
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#.
This morning I thought I was getting somewhere, successfully getting back
the correct answers to a C++ " int SumArray(int ray[], int count)"

Now I'm having problems with C++ "return(false)" being True in C#.

Here is the C# code.
=========================
using System;
using System.Runtime.InteropServices; //
namespace GUI_03
{

class Class1
{
[DllImport("Test05.dll")]
public static extern bool IsEven(int num);

[DllImport("Test05.dll")]
public static extern bool retFalse(int num);

[STAThread]
static void Main(string[] args)
{
for (int i=0; i<5; i++)
{
Console.WriteLine(
"IsEven({0}) = {1} \t retFalse({0}) = {2}",
i, IsEven(i), retFalse(i));
}

Console.ReadLine();
}
}
}

=========================
Next, the initial C++ code.

// Starting point:
// http://www.codeproject.com/csharp/UseCDLLlibinCS.asp

#include <stdio.h>

extern "C"
{
__declspec(dllexport) bool IsEven(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}

__declspec(dllexport) bool retFalse(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}
}

=========================
This is the output.

IsEven(0) = True retFalse(0) = True
IsEven(1) = False retFalse(1) = False
IsEven(2) = True retFalse(2) = True
IsEven(3) = False retFalse(3) = False
IsEven(4) = True retFalse(4) = True

Both "return(true);" and "return(false);" are working.

=========================
This is the code after commenting out everything in retFalse() except
"return(false);"

// Starting point:
// http://www.codeproject.com/csharp/UseCDLLlibinCS.asp

#include <stdio.h>

extern "C"
{
__declspec(dllexport) bool IsEven(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}

__declspec(dllexport) bool retFalse(int somenum)
{
/*if (somenum == (somenum / 2 * 2))
return(true);
else */
return(false);
}
}

=========================
This is the output.

IsEven(0) = True retFalse(0) = True
IsEven(1) = False retFalse(1) = True
IsEven(2) = True retFalse(2) = True
IsEven(3) = False retFalse(3) = True
IsEven(4) = True retFalse(4) = True

Why isn't retFalse always False??
=========================
Here is another function showing things I tried that didn't work...

__declspec(dllexport) bool TorF(int num)
{
//return(true);
//return(false);
//return(1 == 0);
//bool ret = false;
//return(ret);
// if(num == (num / 2 * 2)) // IsEven(num)
//return(true);
return(false);
// else
//return(false);
// return(true);
}
=========================

Any suggestions?

Thanks.

-- Mark
Nov 17 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
On Tue, 29 Mar 2005 14:38:06 -0500, Mark Jerde wrote:
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#.
This morning I thought I was getting somewhere, successfully getting back
the correct answers to a C++ " int SumArray(int ray[], int count)"

Now I'm having problems with C++ "return(false)" being True in C#.


There's a known bug in this area. See if this message applies to your
problem:

http://groups-beta.google.com/group/...UTF-8&oe=UTF-8

--
Doug Harrison
Microsoft MVP - Visual C++
Nov 17 '05 #2

P: n/a
Doug Harrison [MVP] wrote:
Now I'm having problems with C++ "return(false)" being True in C#.


There's a known bug in this area. See if this message applies to your
problem:

http://groups-beta.google.com/group/...UTF-8&oe=UTF-8

Wow, that was fast! Thanks!!

-- Mark
Nov 17 '05 #3

P: n/a

"Mark Jerde" <ma********@verizon.no.spam.net> wrote in message
news:eq**************@TK2MSFTNGP12.phx.gbl...
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#.
This morning I thought I was getting somewhere, successfully getting back
the correct answers to a C++ " int SumArray(int ray[], int count)"

Now I'm having problems with C++ "return(false)" being True in C#.

Here is the C# code.
=========================
using System;
using System.Runtime.InteropServices; //
namespace GUI_03
{

class Class1
{
[DllImport("Test05.dll")]
public static extern bool IsEven(int num);

[DllImport("Test05.dll")]
public static extern bool retFalse(int num);

[STAThread]
static void Main(string[] args)
{
for (int i=0; i<5; i++)
{
Console.WriteLine(
"IsEven({0}) = {1} \t retFalse({0}) = {2}",
i, IsEven(i), retFalse(i));
}

Console.ReadLine();
}
}
}

=========================
Next, the initial C++ code.

// Starting point:
// http://www.codeproject.com/csharp/UseCDLLlibinCS.asp

#include <stdio.h>

extern "C"
{
__declspec(dllexport) bool IsEven(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}

__declspec(dllexport) bool retFalse(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}
}

=========================
This is the output.

IsEven(0) = True retFalse(0) = True
IsEven(1) = False retFalse(1) = False
IsEven(2) = True retFalse(2) = True
IsEven(3) = False retFalse(3) = False
IsEven(4) = True retFalse(4) = True

Both "return(true);" and "return(false);" are working.

=========================
This is the code after commenting out everything in retFalse() except
"return(false);"

// Starting point:
// http://www.codeproject.com/csharp/UseCDLLlibinCS.asp

#include <stdio.h>

extern "C"
{
__declspec(dllexport) bool IsEven(int somenum)
{
if (somenum == (somenum / 2 * 2))
return(true);
else
return(false);
}

__declspec(dllexport) bool retFalse(int somenum)
{
/*if (somenum == (somenum / 2 * 2))
return(true);
else */
return(false);
}
}

=========================
This is the output.

IsEven(0) = True retFalse(0) = True
IsEven(1) = False retFalse(1) = True
IsEven(2) = True retFalse(2) = True
IsEven(3) = False retFalse(3) = True
IsEven(4) = True retFalse(4) = True

Why isn't retFalse always False??
=========================
Here is another function showing things I tried that didn't work...

__declspec(dllexport) bool TorF(int num)
{
//return(true);
//return(false);
//return(1 == 0);
//bool ret = false;
//return(ret);
// if(num == (num / 2 * 2)) // IsEven(num)
//return(true);
return(false);
// else
//return(false);
// return(true);
}
=========================

Any suggestions?

Thanks.

-- Mark


Should be...
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

Lookup the MSDN docs, an ansi C "bool" is a single byte value, true = 1, 0 =
false, you should declare it as a I1 return when PInvoking !
A BOOL in C (typedef used in a great number of windows API's) is a 4 byte
value wich is marshaled correctly to bool.

Willy.

Nov 17 '05 #4

P: n/a

"Doug Harrison [MVP]" <ds*@mvps.org> wrote in message
news:r4*****************************@40tude.net...
On Tue, 29 Mar 2005 14:38:06 -0500, Mark Jerde wrote:
I'm trying to learn the very basics of using an unmanaged C++ DLL from
C#.
This morning I thought I was getting somewhere, successfully getting back
the correct answers to a C++ " int SumArray(int ray[], int count)"

Now I'm having problems with C++ "return(false)" being True in C#.


There's a known bug in this area. See if this message applies to your
problem:

http://groups-beta.google.com/group/...UTF-8&oe=UTF-8

--
Doug Harrison
Microsoft MVP - Visual C++


Doug ,

It' somewhat related but it's not a bug in PInvoke interop, it was a bug in
managed C++ IJW interop.
The problem is that ansi C defines bool as a single byte intrinsic value,
but most of windows API's (predating ansi C) return a BOOL which is a 4 byte
value (a typedef), therefore the Interop team decided to marshal by default
to/from BOOL for PInvoke interop.
If you need to marshal to/from a C bool you have to marshal as a
UnmanagedType.I1,
or as in OP's case...
[return:MarshalAs(UnmanagedType.I1)]

Willy.
Nov 17 '05 #5

P: n/a
Willy Denoyette [MVP] wrote:
Should be...
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

Lookup the MSDN docs, an ansi C "bool" is a single byte value, true =
1, 0 = false, you should declare it as a I1 return when PInvoking !
A BOOL in C (typedef used in a great number of windows API's) is a 4
byte value wich is marshaled correctly to bool.

Willy.


Willy -- Thanks for the detailed notes to Doug and me, I'll try to figure
out their meaning. It would certainly be better to fix it on the C# side.

-- Mark
Nov 17 '05 #6

P: n/a
"Mark Jerde" <ma********@verizon.no.spam.net> wrote in message
news:eq**************@TK2MSFTNGP12.phx.gbl...
I'm trying to learn the very basics of using an unmanaged C++ DLL from C#.
This morning I thought I was getting somewhere, successfully getting back
the correct answers to a C++ " int SumArray(int ray[], int count)"

Now I'm having problems with C++ "return(false)" being True in C#.


I see that Doug and Willy have already weighed in on the matter.

FWIW, this bug bit me too. For native functions that return bool and which
may be invoked from managed code, I have taken to changing what I might have
written like this

bool foo(...)
{
bool ok;

// ... set ok

return ok;
}

to this

bool foo(...)
{
bool ok;

// ... set ok

__asm xor eax, eax
return ok;
}

Regards,
Will


Nov 17 '05 #7

P: n/a
William DePalo [MVP VC++] wrote:
__asm xor eax, eax
return ok;
}


Is this portable to Linux? <g>

-- Mark
Nov 17 '05 #8

P: n/a
Willy Denoyette [MVP] wrote:
Should be...
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

Lookup the MSDN docs, an ansi C "bool" is a single byte value, true =
1, 0 = false, you should declare it as a I1 return when PInvoking !
A BOOL in C (typedef used in a great number of windows API's) is a 4
byte value wich is marshaled correctly to bool.


Willy -- Thanks, the below works fine, and I even finally found the
UnmanagedType Enumeration. ;-)

[DllImport("Test05.dll")]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

A further question is how to have known about this beforehand. I'm
wondering about my other data types and whether they will marshall correctly
in *all* cases. My other return is an int which I presume is ok.
Arguements include integers, arrays of integers, arrays of bytes (arrays of
unsigned chars in C++) and arrays of structures. (The structure members are
just integers, no string stuff.) I have a sample program that uses

[StructLayout(LayoutKind.Sequential)]

Do you see anything in these types I should look out for?

Thanks.

-- Mark
Nov 17 '05 #9

P: n/a

"Mark Jerde" <ma********@verizon.no.spam.net> wrote in message
news:uH**************@TK2MSFTNGP14.phx.gbl...
Willy Denoyette [MVP] wrote:
Should be...
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

Lookup the MSDN docs, an ansi C "bool" is a single byte value, true =
1, 0 = false, you should declare it as a I1 return when PInvoking !
A BOOL in C (typedef used in a great number of windows API's) is a 4
byte value wich is marshaled correctly to bool.


Willy -- Thanks, the below works fine, and I even finally found the
UnmanagedType Enumeration. ;-)

[DllImport("Test05.dll")]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool retFalse(int num);

A further question is how to have known about this beforehand. I'm
wondering about my other data types and whether they will marshall
correctly
in *all* cases. My other return is an int which I presume is ok.
Arguements include integers, arrays of integers, arrays of bytes (arrays
of
unsigned chars in C++) and arrays of structures. (The structure members
are
just integers, no string stuff.) I have a sample program that uses

[StructLayout(LayoutKind.Sequential)]

Do you see anything in these types I should look out for?

Thanks.

-- Mark


Mark,

Note that we must make a clear distinction between PInvoke interop, and the
IJW (It Just Works) interop feature available in managed C++ only.
The former uses the CLR to marshal arguments and return values when calling
into unmanaged code from managed code, the latter doesn't use the CLR
marshaling but instead puts the burden on the user to correctly marshal
argument/return types when they tend to be incompatible.
Each managed type has a default marshaling behavior associated when using
PInvoke interop.
For instance a managed int (32 bit signed value) will be passed unchanged,
however, a managed string (Unicode char string) will be converted to/from a
char string (Ansi char string) by default.
This default behavior can be changed by tagging the MarshalAs attribute to
the arg. or return type.
For instance if your unmanaged counter part expects a string to be UNICODE,
you should tag the string argument with a MarshalAs(UnmanagedType.LPWSTR)
attribute and the CLR will pass the string unchanged.
Now back to our bool type. The default marshaling passes a bool as a 32 bit
integer, which is a reasonable default when the unmanaged code expects a
BOOL (32 bit integer value) as used by most of the Win32 API's. However,
when passing ANSI C bool type, you have to change the default behavior by
means of the
MarshalAs(UnmanagedType.I1) attribute. Failing to do this results in
unexpected behavior as you noticed, using the trick as suggested by William
is not needed when using PInvoke interop.
I suggest you to check the list of managed types and try to understand their
default marshaling behavior when using PInvoke marshaling, also take some
time to understand the default alignment/packing used at both the managed
side and the unmanaged side.

Willy.

Nov 17 '05 #10

P: n/a
Willy Denoyette [MVP] wrote:
I suggest you to check the list of managed types and try to
understand their default marshaling behavior when using PInvoke
marshaling, also take some time to understand the default
alignment/packing used at both the managed side and the unmanaged
side.


Willy -- Thanks for the reply. I think I'm starting to understand.
For the possible benefit of future googlers here are MSDN links.

Interoperating with Unmanaged Code
http://msdn.microsoft.com/library/de...anagedCode.asp

Interop Marshaling
http://msdn.microsoft.com/library/de...marshaling.asp

An Overview of Managed/Unmanaged Code Interoperability
http://msdn.microsoft.com/library/de...nunmancode.asp

-- Mark
Nov 17 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.