interfacing with stdbool.h C++

2019-02-12 09:23发布

问题:

In a project I am interfacing between C++ and a C library that uses stdbool.h defined as such.

#ifndef _STDBOOL_H
#define _STDBOOL_H

/* C99 Boolean types for compilers without C99 support */
/* http://www.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html */
#if !defined(__cplusplus)

#if !defined(__GNUC__)
/* _Bool builtin type is included in GCC */
typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool;
#endif

#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1

#endif

#endif

Some structures have bool members. So if I have one of these structures defined as local variables within a C++ function and pass it to a C function the sizes are inconsistent between C++ and C as bool is one bye in C++ and 4 in C.

Does anyone have any advice to how to overcome this without resorting to my current solution which is

//#define bool _Bool
#define bool unsigned char

Which is against the C99 standard for stdbool.h

回答1:

I found the answer to my own question by finding a more compatible implementation of stdbool.h that is compliant with the C99 standard.

#ifndef _STDBOOL_H
#define _STDBOOL_H

#include <stdint.h>

/* C99 Boolean types for compilers without C99 support */
/* http://www.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html */
#if !defined(__cplusplus)

#if !defined(__GNUC__)
/* _Bool builtin type is included in GCC */
/* ISO C Standard: 5.2.5 An object declared as 
type _Bool is large enough to store 
the values 0 and 1. */
/* We choose 8 bit to match C++ */
/* It must also promote to integer */
typedef int8_t _Bool;
#endif

/* ISO C Standard: 7.16 Boolean type */
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1

#endif

#endif

This is taken from the Ada Class Library project.



回答2:

Size is not the only thing that will be inconsistent here. In C++ bool is a keyword, and C++ guarantees that a bool can hold a value of either 1 or 0 and nothing else. C doesn't give you this guarantee.

That said, if interoperability between C and C++ is important you can emulate C's custom-made boolean by defining an identical one for C++ and using that instead of the builtin bool. That will be a tradeoff between a buggy boolean and identical behaviour between the C boolean and the C++ boolean.



回答3:

Logically, you are not able to share source code between C and C++ with conflicting declarations for bool and have them link to each other.

The only way you can share code and link is via an intermediary datastructure. Unfortunately, from what I understand, you can't modify the code that defines the interface between your C++ program and C library. If you could, I'd suggest using something like:

union boolean {
   bool value_cpp;
   int  value_c;
}; 

// padding may be necessary depending on endianness

The effect of which will be to make the datatype the same width in both languages; conversion to the native data type will need to be performed at both ends. Swap the use of bool for boolean in the library function definition, fiddle code in the library to convert, and you're done.

So, what you're going to have to do instead is create a shim between the C++ program and the C library.

You have:

extern "C" bool library_func_1(int i, char c, bool b);

And you need to create:

bool library_func_1_cpp(int i, char c, bool b)
{
   int result = library_func_1(i, c, static_cast<int>(b));
   return (result==true);
}

And now call library_func_1_cpp instead.