How to handle calling convention when wrapping C-code in Cython? [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to interface PDFium with Cython and ran into these defines/signatures:
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __declspec(dllexport)
#else
#define FPDF_EXPORT __declspec(dllimport)
#endif // defined(FPDF_IMPLEMENTATION)
#else
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __attribute__((visibility("default")))
#else
#define FPDF_EXPORT
#endif // defined(FPDF_IMPLEMENTATION)
#endif // defined(WIN32)
#else
#define FPDF_EXPORT
#endif // defined(COMPONENT_BUILD)
#if defined(WIN32) && defined(FPDFSDK_EXPORTS)
#define FPDF_CALLCONV __stdcall
#else
#define FPDF_CALLCONV
#endif
FPDF_EXPORT void FPDF_CALLCONV
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config);
I'm just used to the simple function declaration with
return_type function_name();
How to wrap signatures containing calling conventions in Cython?

Unfortunately, I could not find the specific macros or the function you reference here: https://github.com/PDFium/PDFium
You should probably add what specific version of your library you are using.
However, there are things in C function declarations besides return type, function name, and parameters that come from outside C it self.
One specific one, which is not part of the C standard, is the calling convention, which specifies how sending parameters and returning from function works.
Since the keywords to specify this convention are compiler specific, it makes sense to put them in a conditional macro, to make the code portable.
It may also be done to support cross-compilation for different hardware.
So FPDF_CALLCONV is most likely something like this:
#ifdef SOME_CONDITION_TO_USE_STD_CALL
#define FPDF_CALLCONV __stdcall
#endif
Another non standard option in C (and C++) programs is a directive to export a function when building a DLL on Windows.
Since this is platform specific, to make C code cross-platform, it also needs to be in a conditional macro.
So, FPDF_EXPORT is likely something like this:
#ifdef WINDOWS
#define FPDF_EXPORT __declspec(dllexport)
#else
#define FPDF_EXPORT
#endif
Note, that on other platforms this kind of "marking" does not exist, so the macro can expand to nothing, leaving the function declaration in a more familiar form.
It should also be left blank in the version of h file you include to use the library as opposed to the one used to compile the library, as you don't need this prefix to call the function.
To conclude, it is likely you can omit these two macros in your Cuthon interface, assuming the library you are using is compatible with your platform.

FPDF_EXPORT and FPDF_CALLCONV are Macros, they are defined in the file :
https://pdfium.googlesource.com/pdfium/+/master/public/fpdfview.h
They are needed here because the library is available for different systems, and different systems have different conventions for creating the library interface.
These calls are extensions to the format you are familiar with:
return_type function_name(args)
For example you can see that FPDF_CALLCONV dissapears unless you are building the library for windows.

Related

How to #ifdef the __builtin_prefetch function

How do I keep __builtin_prefetch() in my code, but make compilers that do not have it compile successfully? (Just doing nothing where it is found).
__builtin_prefetch() is recognised by the compiler (gcc) not the preprocessor, so you won't be able to detect it using the C preprocessor.
Since an identifier with two leading underscores is reserved for use by the implementation (so any code you use which defines such an identifier has undefined behaviour) I'd do it the other way around.
#ifdef __GNUC__
#define do_prefetch(x) __builtin_prefetch(x)
#else
#define do_prefetch(x)
#endif
and then use
do_prefetch(whatever);
where needed.
That way there is no code emitted unless it is actually needed.
Since __builtin_prefetch() accepts a variable number of arguments, you might want to adapt the above to use variadic macros (C99 and later) - if you use it with different numbers of arguments in different places in your code.
It is not exactly the best solution, but it will disable __builtin_prefetch() on all other compilers other than GCC.
#ifndef __GNUC__
# define __builtin_prefetch(x)
#endif

How do I check if I can use <sys/statvfs.h>?

I want to write a portable way to get the free disk space. On Windows, I use GetDiskFreeSpaceEx, and on Linux, the header <sys/statvfs.h> contains the function statvfs64() I can use.
My question is, on which systems I can assume that this header exists. Is there a macro I can check? Something like
#ifdef _MSC_VER
#include <windows.h>
#else
#ifdef STATVFS_IS_AVAILABLE
#include <sys/statvfs.h>
#endif
#endif
Generally, you would use autotools for stuff like that. autoconf creates a config.h header which defines a HAVE_STATVFS or so macro if you define a suitable configuration test.
However, due to the otherwise huge availability of <sys/statvfs.h>, you can also less portably simply test for _MSC_VER, as you just did.

How to avoid that C-header overwrites native C++ type

First I have to explain my ...
Situation
I have this microcontroller code (plain old C) which includes bool.h with the following content since stdbool.h is apparently not available, especially not with Visual Studio 2008, which is my current IDE for VC++ and C# (see below):
#ifndef CUSTOM_BOOL
#define CUSTOM_BOOL
#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus
#ifndef bool
#define bool unsigned char
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
#endif // #ifndef CUSTOM_BOOL
Now I need the functionality of that microcontroller code in a C# Project. That's why I created an intermediate Visual C++ Project containing managed classes that wrap the given microcontroller code.
Since this wrapper project (VC++) fiddles about the C code, it also has to #include "bool.h" (in an indirect way however, which means that another header is included, which itself includes bool.h - but I think that's an unimportant detail). Now here's my ...
Problem
Due to the fact that bool.h is included in the VC++ project and this project shall provide functions that return a "real" bool ("real" here means a type that is recognized as a bool by C# when using the VC++ project), unfortunately the bool in the VC++ code is also caught by the preprocessor and thus replaced by unsigned char. What happens now is, that C# complains in the end that a conversion from unsigned char to bool is not allowed. This is all okay and I understand why this happens. So here's my ...
Question
How can I solve this issue in a "clean" way. My current solution is, after including bool.h and right before the VC++ code starts, I undefine bool and friends again like this:
#ifdef bool
#undef bool
#endif
#ifdef true
#undef true
#endif
#ifdef false
#undef false
#endif
It works, but it breaks my proper-way-of-programming-heart. Is there a proper way to fix this? Or is the problem maybe happening before? Should I instead define something like BOOL instead of bool? According to my search on the interwebz, there is no general "standard" way to define bool (or BOOL?) in a C project (C99 is not supported) that everybody would agree upon.
So it sounds like the microcontroller project just made up a new data type and called it bool, which happens to conflict now that bool is a keyword (along with true and false)? My suggestions (in order of preference) would be:
Solution 1: Fix the microcontroller project.
Do a global search and replace on bool and replace it with something less contentious. Maybe C_Boolean, C_True, and C_False. Unlikely to cause any future conflicts and fairly simple to do using regular expressions.
Solution 2: Convert microcontroller project to C++.
This allows direct use of bool, true, and false (as keywords) and you can just eliminate the macros. This may prove difficult if the microcontroller code uses syntax that isn't c++ compatible.
Solution 3: Do what you've already done.
Create a wrapper include which cleans up after including your microcontroller code. I've got code that relies on redefining the extern keyword and this ends up being the only safe way for me. It's fragile though...you'll likely have to fix it in the future when something unrelated breaks the include structure.
Also, I'm not sure what the original author believes the extern "C" wrappers are doing but they have no effect on the macros being defined. Maybe you cut out some stuff that it would have an effect on, but the macros are unaffected by the linker name conventions.
You could convert the return value (the char) to a boolean value by using an operator. In this case, for instance, you could simply compare the return value this way:
bool b = 0 != functionthatreturnsaboolean();
Note that I'm not using 1 since the usualt definition of a boolean is 0 for false, anything else otherwise.
The other solution would be to simply use another type of return value. An integer should work well.
Edit: In light of the comment - you could also simply create an interface that calls those functions and returns a C# boolean value.
bool interfacefunction()
{
return function() != 0;
}
Thanks to Keith Thompson (comment under the question) and Speed8ump's answer, I got another idea:
bool.h:
#ifndef CUSTOM_BOOL
#define CUSTOM_BOOL
#ifndef __cplusplus
#ifndef bool
#define bool unsigned char
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif // #ifndef __cplusplus
#endif // #ifndef CUSTOM_BOOL
Works like a charm and I think it's a cleaner solution than the undefining stuff before. But still, feel free to comment or to provide more / better answers.

How to test if a header has already been included before [duplicate]

This question already has answers here:
Purpose of Header guards
(2 answers)
Closed 9 years ago.
I'm making a project, and I get stunned with a problem.
I have 3 libraries.h that includes another special library, definitions.h, but in my Main module, i want to include all the libraries just one time, I mean, I want to test if the library definitions.h has already been included, and include it or not depending on the result.
Something like
If !(#include"definitions.h")
(#include"definitions.h")
You are looking for include guards.
Example,
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
...
...
#endif
#ifndef DEFINITIONS_H
#define DEFINITIONS_H
//lots of code
//
//
//
//
#endif
There's also non-standard #pragma once, see Is #pragma once a safe include guard?
If your header syntax is correct, this should not be a problem. In fact, this is the reason why you write
#ifndef _DEFINITIONS_H
#define _DEFINITIONS_H
[header content]
#endif
So, if your header is conform to C conventions, you should be fine.

How to #ifdef by CompilerType ? GCC or VC++

I used #ifdef Win32 for safe calls alike sprintf_s but now I want to build project with MinGW and it's just wrong now. I need to use #ifdef VC++ or somehow like that. Is it possible?
#ifdef __clang__
/*code specific to clang compiler*/
#elif __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif
See the "Microsoft-Specific Predefined Macros" table of Visual C predefined macros
You could check for _MSC_VER.
Preferably, you should resort to using portable symbols. I understand sometimes those symbols may not be defined, so you can see the Predef project for an extensive list of preprocessor macros regarding standards, compilers, libraries, operating systems and architectures that aren't portable.
However, the function you specifically mention in this question has been included within the C11 standard as a part of Annex K.3, the bounds-checking interfaces (library).
K.3.1.1p2 states:
The functions, macros, and types declared or defined in K.3 and its subclauses are declared and defined by their respective headers if __STDC_WANT_LIB_EXT1__ is defined as a macro which expands to the integer constant 1 at the point in the source file where the appropriate header is first included
Thus, you should place preference upon checking __STDC_WANT_LIB_EXT1__, and only use compiler-specific symbols when that doesn't exist.

Resources