473,383 Members | 1,919 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Unmanaged C++ Dll / C# bool return problem

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
10 19092
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
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

"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

"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
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
"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
William DePalo [MVP VC++] wrote:
__asm xor eax, eax
return ok;
}


Is this portable to Linux? <g>

-- Mark
Nov 17 '05 #8
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

"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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Chiller | last post by:
I wish to implement overloads of six comparison operators (==, !=, <, <=, >, >=), which will return true or false when comparing two distance values. I've added the code below to my Distance...
7
by: Kristof Thys via .NET 247 | last post by:
Post a new message to microsoft.public.dotnet.languages.vc http://www.dotnet247.com/247reference/default.aspx Hello, I've been struggling for weeks with this problem, I hope I find some...
1
by: Don.Leri | last post by:
Hi, I have a logger.dll (unmanaged c++ dll compiled in vs2005). I have a C# interop to use that dll in managed code implemented in Interfaces.dll (used by other C# dlls). I also have a...
16
by: DaTurk | last post by:
Hi, I have a c# application that needs to access c++ libraries, so it does this by using a managed layer of c++ CLI. Anyway, in the CLI function call, that calls the unmanaged function it...
1
by: Paolo Pagano | last post by:
I have a VS2005 solution with two projects: 1) a .net windows forms application (which references) 2) a managed C++ CLR library (using MFC ia a Shared DLL) .
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.