How to create interface file for SWIG - c

I have the following header files:
gaiageo.h
which is defined as
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/* stdio.h included for FILE objects. */
#include <stdio.h>
#ifdef DLL_EXPORT
#define GAIAGEO_DECLARE __declspec(dllexport)
#else
#define GAIAGEO_DECLARE extern
#endif
#endif
#ifndef _GAIAGEO_H
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define _GAIAGEO_H
#endif
#include "gg_const.h"
#include "gg_structs.h"
#include "gg_core.h"
#include "gg_mbr.h"
#include "gg_formats.h"
#include "gg_dynamic.h"
#include "gg_advanced.h"
#endif /* _GAIAGEO_H */
The included header files are riddled with GAIAGEO_DECLARE, for
instance gg_formats.h (which is very typical of the included headers) has the following:
/**
\file gg_formats.h
Geometry handling functions: formats
*/
#ifndef _GG_FORMATS_H
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define _GG_FORMATS_H
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/* function prototypes */
/**
Test CPU endianness
\return 0 if big-endian: any other value if little-endian
*/
GAIAGEO_DECLARE int gaiaEndianArch (void);
/**
Import an INT-16 value in endian-aware fashion
\param p endian-dependent representation (input buffer).
\param little_endian 0 if the input buffer is big-endian: any other value
for little-endian.
\param little_endian_arch the value returned by gaiaEndianArch()
\return the internal SHORT value
\sa gaiaEndianArch, gaiaExport16
\note you are expected to pass an input buffer corresponding to an
allocation size of (at least) 2 bytes.
*/
GAIAGEO_DECLARE short gaiaImport16 (const unsigned char *p,
int little_endian,
int little_endian_arch);
#ifdef __cplusplus
}
#endif
#endif /* _GG_FORMATS_H */
This is my first attempt at creating interface files and would like some help, online documentation is confusing me?
Should I be creating an interface file for each header and how should I create the interface for the encompassing gaiageo.h?

This should get you started, but it is difficult to know exactly what you'll need.
%include <windows.i> makes SWIG handle Window-isms like __declspec(dllexport).
SWIG does not recurse include files by default, so include the ones you need SWIG to process. There is a switch to recurse, but then it would process stdio.h.
%module gaiageo
%{
#include "gaiageo.h"
%}
%include <windows.i>
%include "gaiageo.h"
%include "gg_const.h"
%include "gg_structs.h"
%include "gg_core.h"
%include "gg_mbr.h"
%include "gg_formats.h"
%include "gg_dynamic.h"
%include "gg_advanced.h"
Save that as a gaiageo.i file and run something like:
swig -c++ -<target_language> gaiageo.i

Related

Why can't I have an inner structure when two files include each other?

For context, I'm writing an operating system:
I have a struct vt_device_s and a struct __vt_device_s which is architecture specific and lives inside of vt_device_s like so:
struct
vt_device_s
{
struct __vt_device_s __device;
size_t cursor_x;
size_t cursor_y;
};
Now for the architectural struct:
struct
__vt_device_s
{
uint16_t *memory;
size_t memory_len;
};
The header <dev/vt.h> knows about __vt_device_s defined in <sys/_vt.h> because it is included, yet I get this error:
error: field '__device' has incomplete type
48 | struct __vt_device_s __device;
|
I realise this is because both files rely on each other (the whole conflict is caused by _vt.c including _vt.h including vt.h including _vt.h) but I don't understand how it is a compile problem. I have include guards in both files!
PS: I understand this would be a non-issue if I used a pointer but as it's an operating system, this driver needs to function before paging is set up (that is, malloc and free don't exist yet).
Here are the three files in question:
dev/vt.h
#ifndef _DEV_VT_H_
#define _DEV_VT_H_ 1
#include <stddef.h>
#include <sys/_vt.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct
vt_device_s
{
struct __vt_device_s __device;
size_t cursor_x;
size_t cursor_y;
};
void vt_init(struct vt_device_s *);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _DEV_VT_H_ */
sys/_vt.h
#ifndef _I386__VT_H_
#define _I386__VT_H_ 1
#include <stddef.h>
#include <stdint.h>
#include <dev/vt.h>
#define __VT_WIDTH 80
#define __VT_HEIGHT 25
#define __VT_MEMOFF 0xb8000
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct
__vt_device_s
{
uint16_t *memory;
size_t memory_len;
};
void __vt_init(struct vt_device_s *);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _I386__VT_H_ */
sys/_vt.c
#include <sys/_vt.h>
void
__vt_init(struct vt_device_s *device)
{
device->__device.memory = (uint16_t *) __VT_MEMOFF;
device->__device.memory_len = __VT_WIDTH * __VT_HEIGHT;
}
Your double include guards prevent the one file from including itself when it is re-included by the other. The only way to fix this is you have got to break the cycle. Decide which header is "higher" and will include the "lower" and don't try to include the higher one from the lower one. The lower one must be valid on its own.
The reason for this is that the pre-processor has to transform multiple files into one linear sequence of lines for the compiler. The compiler has to see one set of file contents before the other.
If you have cyclic includes like this you make it up to the final user of the code which one comes first. If they include file A, then it will include file B, which will try to include file A again but it will be prevented by the include guards, so the contents of B will be parsed first. On the other hand if the final user includes B first, then the contents of A will be seen first by the compiler.
So if you leave it like it is, then it is effectively random which file gets included first. If you break the cycle, you get to decide yourself which is included first.
Once you have decided, you can fix the compiler errors about incomplete types by making whichever file you choose to put first able to stand on its own and then letting the one that is second use definitions from the first.

multiple definition error in Clion

I added "Mersenne Twist Pseudorandom Number Generator Package" (one header file and one source file) to my Clion C project, but I can not build the project.
the error is :
multiple definition of `mts_lrand'
I can successfully compile and run the program using just command line and gcc but in Clion i can not.
I think it has something to do with macros, but I do not know how to fix it.
here is some part of the code i added:
mtwist.h
.
.
.
.
/*
* In gcc, inline functions must be declared extern or they'll produce
* assembly code (and thus linking errors). We have to work around
* that difficulty with the MT_EXTERN define.
*/
#ifndef MT_EXTERN
#ifdef __cplusplus
#define MT_EXTERN /* C++ doesn't need static */
#else /* __cplusplus */
#define MT_EXTERN extern /* C (at least gcc) needs extern */
#endif /* __cplusplus */
#endif /* MT_EXTERN */
/*
* Make it possible for mtwist.c to disable the inline keyword. We
* use our own keyword so that we don't interfere with inlining in
* C/C++ header files, above.
*/
#ifndef MT_INLINE
#define MT_INLINE inline /* Compiler has inlining */
#endif /* MT_INLINE */
/*
* Try to guess whether the compiler is one (like gcc) that requires
* inline code to be available in the header file, or a smarter one
* that gets inlines directly from object files. But if we've been
* given the information, trust it.
*/
#ifndef MT_GENERATE_CODE_IN_HEADER
#ifdef __GNUC__
#define MT_GENERATE_CODE_IN_HEADER 1
#endif /* __GNUC__ */
#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
#define MT_GENERATE_CODE_IN_HEADER 0
#endif /* __INTEL_COMPILER || _MSC_VER */
#endif /* MT_GENERATE_CODE_IN_HEADER */
#if MT_GENERATE_CODE_IN_HEADER
/*
* Generate a random number in the range 0 to 2^32-1, inclusive, working
* from a given state vector.
*
* The generator is optimized for speed. The primary optimization is that
* the pseudorandom numbers are generated in batches of MT_STATE_SIZE. This
* saves the cost of a modulus operation in the critical path.
*/
MT_EXTERN MT_INLINE uint32_t mts_lrand(
register mt_state* state) /* State for the PRNG */
{
register uint32_t random_value; /* Pseudorandom value generated */
if (state->stateptr <= 0)
mts_refresh(state);
random_value = state->statevec[--state->stateptr];
MT_PRE_TEMPER(random_value);
return MT_FINAL_TEMPER(random_value);
}
.
.
.
.
you see the function definition is in header file, i think this is the problem but I don't know what to do
you can see complete code here.

Redefined symbol in multiple c code with #ifndef directive

I have a stupid problem and I don't see where it comes from. I took care of using #ifndef directive to make sure all my #include are not redefined. Sadly for three of them that's happening. Here my multiple files arch :
t_include.h
#ifndef T_INCLUDE_H_
#define T_INCLUDE_H_
/* Project specific dependencies*/
#include "utilities.h"
#include "fsp_function.h"
#include "ti/csl/csl_tsc.h"
#include "ti/csl/csl_cache.h"
#include "ti/csl/csl_cacheAux.h"
#include "ti_sp_complex_convolution_A_input1.h"
#include "ti_sp_complex_convolution_A_input2.h"
#include "to_sp_complex_convolution_A_output.h"
#endif /* T_INCLUDE_H_ */
t_function.h
#ifndef T_FUNCTION_H_
#define T_FUNCTION_H_
#include "t_include.h"
/*output vector*/
#define INPUT1A_LENGTH 5000
#define INPUT2A_LENGTH 2800
#define OUTPUTA_LENGTH 2202
extern FLOAT32 sp_complex_convolution_A_output_thales[OUTPUTA_LENGTH];
/*misc parameter*/
#define CPU_CLOCK_KHZ 1400000
#define CPU_CLOCK_MS 1/CPU_CLOCK_KHZ
#define FIR_NB_MACS INPUT1A_LENGTH * OUTPUTA_LENGTH /* FIR algorithm complexity */
#define NB_OF_REP 10
#define UMA_L2CACHE_L1DCACHE 0
/* Project specific types */
typedef struct{
ect...
And now c file only include t_function.h :
t_function.c
/* Dependencies */
#include "t_function.h"
FLOAT32 sp_complex_convolution_A_output_thales[OUTPUTA_LENGTH];
/* API */
etc...
And t_main_function.c
/* dependencies */
#include "t_function.h"
void main(void) {
etc...
It should work but during linking here the errors comming :
<Linking>
error #10056: symbol "sp_complex_convolution_A_output" redefined: first defined in "./TEST/t_function.obj"; redefined in "./TEST/t_main_function.obj"
error #10056: symbol "sp_complex_convolution_A_input2" redefined: first defined in "./TEST/t_function.obj"; redefined in "./TEST/t_main_function.obj"
error #10056: symbol "sp_complex_convolution_A_input1" redefined: first defined in "./TEST/t_function.obj"; redefined in "./TEST/t_main_function.obj"
error #10056: symbol "sp_complex_convolution_A_output_thales" redefined: first defined in "./TEST/t_function.obj"; redefined in "./TEST/t_main_function.obj"
>> Compilation failure
error #10010: errors encountered during linking; "CONVOLUTION_COMPLEX.out" not built
So the error only com from three symbol sp_complex_convolution_A_output, sp_complex_convolution_A_input1 and sp_complex_convolution_A_input2 Which are defined in their own .h which is also protected by #ifndef directives:
ti_sp_complex_convolution_A_input1.h
#ifndef __TI_SP_COMPLEX_CONVOLUTION_A_INPUT1_H_
#define __TI_SP_COMPLEX_CONVOLUTION_A_INPUT1_H_
FLOAT32 sp_complex_convolution_A_input1[2 * 2500] = {
etc...
And the same for the other two...
So I really don't know why it is happening.
Thx for helping
Definitions like:
FLOAT32 sp_complex_convolution_A_output_thales[OUTPUTA_LENGTH];
should go into a source file.
The header files should contain only declarations like:
extern FLOAT32 sp_complex_convolution_A_output_thales[OUTPUTA_LENGTH];
As a rule of thumb, do no put anything that allocates memory into header files.

Function declared twice in C header file

I'm aware of the declaration of C header files with #ifdef and the meaning of extern before variables and functions. But recently I've got a third party library for an embedded device with the following scheme:
/* "lib.h" */
#ifndef LIB_H_
#define LIB_H_
#ifdef LIB_C
void function1();
/* ... */
#else
extern void function1();
/* ... */
#endif
#endif /* LIB_H_ */
And additionally I've got a corresponding C source file:
/* lib.c */
#define LIB_C
#include "lib.h"
void function1()
{
/* ... */
}
/* ... */
So here I am and a bit confused. What is the reason to declare all functions twice in the header in this way?
It's either an affectation, or a compatibility hack for some non-conforming or ancient compiler. You don't need the extern version, but using it is also fine, because function declarations are extern by default.
In other words, it's cruft, but maybe someone needs that cruft. We can't know for sure.

Multiple inclusion of header file error in C

So I have a header file let's say "header.h" which is protected as follows:
#ifndef __HEADER1_H
#define __HEADER1_H
//type and function def
typedef struct
{
float r; //process noise
float k; //process gain
}state_t;
int get_state(state_t* state, float b);
#endif
Now I have two other headers which I defined as follows:
#ifdef __HEADER2_H
#include "header.h"
//function def
#endif
Second header:
#ifdef __HEADER3_H
//function
//the reason it is done this way is for cnditional compiling such that if the caller
//defines __HEADER3_H t this file won't be included.
#include "header.h"
#endif
Now as I suspected the compiler complained that types and functions defined in header.h were not detected in the source implementation of header2 and header3. So I included header.h in the source files as well. Now the linker is complaining functions that are defined in header.h are multiply defined.
My understanding was since the header.h is protected by ifndef it will only be included once so I don't see the problem.
here is the error that I am getting:
Symbol get_state multiply defined(by kalman.o and dsp.o)
Is there any chance that I am doing something unusally wrong?
#ifndef __HEADER1_H
#define __HEADER_H
The problem is your guard (__HEADER_H) is different from what you are checking for (__HEADER1_H). Make these both the same value.
The typical "guard" for a header file is:
myheader.h:
#ifndef _MYHEADER
#define _MYHEADER
<do stuff>
#endif
Optionally where myheader.h is included, you can do:
#ifndef _MYHEADER
#include "myheader.h"
#endif
This is optional and basically is only to improve compile performance.

Resources