I have C header file containing the following type definition:
// example.h
typedef struct Vertex {
int color;
} Vertex;
I try to wrap this struct with SWIG, but apparently I am doing something wrong. My SWIG interface file looks like
// example.i
%module example
%inline %{
#include "example.h"
}
But if I copy the contents of my header file into my interface file so that the latter looks like
%module example
%inline %{
typedef struct Vertex {
int color;
} Vertex;
%}
I can access the struct from Ruby in the following way
irb> require 'example'
# => true
irb> Examlpe::Vertex
# => Vertex
Is there a way to automatically wrap a header file? I don't want to copy and paste the contents of the header file to the interface file every time I change it.
Thanks in advance for your help.
-- t6d
It's been a while since I used Swig but as I recall %inline is used to pass through the inline part directly to the compiler; Swig itself doesn't see it, What I think you need is:
%module example
%include<example.h>
Related
I am creating a Python wrapper for an existing code base with a DLL and header. I am using SWIG.
The code base has multiple struct pointer defs like so:
typedef struct session* session_t;
In this example, session is not defined anywhere else. All other functions in the DLL take session_t as an input. If I try and reference session anywhere in SWIG generated code I get compile errors that session is not defined. I need a way to access the value of session_t in Python code.
I've tried using cpointer.i and pointer_functions macro, but this doesn't work since it assumes the input type is not a pointer.
I thought if I could redefine the struct:
typedef struct Session {} session, *session_t;
This could work, but I cant find a way to do this with SWIG.
Is there a way to access the value of a struct pointer with SWIG if it's only definition is a typdef struct pointer?
Edit: possible fix is the SWIG %ignore directive. Might be able to ignore the original struct def and replace it in the .i file.
Solved(ish): I marked Mark Tolonen's answer as correct since it has a lot of useful relevant information. The API I'm trying to wrap has a lot of deleted constructors and behaviors locking down how it's used. I ended up writing a C++ wrapper in it's own namespace then telling Swig to ignore everything except my namespace. I then only use standard or my own types to interface with Swig/Python.
SWIG works very well with opaque types. Here's a full example where I've provided the source for a test.dll that uses an opaque typedef. The structure is only defined within the .c file and SWIG has no knowledge of the definition. If you are still having a problem update your question with a reproducible example. I suspect you've used session instead of session_t in some typemap, but without a reproducible example I can only show that it works without a definition.
test.c
#define API_EXPORTS
#include <stdlib.h>
#include "test.h"
struct session {
int a;
};
API session_t alloc(void) {
session_t s = malloc(sizeof(session_t));
if(s)
s->a = 123;
return s;
}
API int get_a(session_t s) {
return s->a;
}
API void release(session_t s) {
free(s);
}
test.h
#ifdef API_EXPORTS
# define API __declspec(dllexport)
#else
# define API __declspec(dllimport)
#endif
typedef struct session* session_t;
API session_t alloc(void);
API int get_a(session_t s);
API void release(session_t session);
test.i
%module test
%{
#include "test.h"
%}
%include <windows.i>
%include "test.h"
test session
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> s = test.alloc()
>>> test.get_a(s)
123
>>> test.release(s)
>>>
I am building a project that I am trying to organize as follows:
main.c
globals.h
structures.h
FunctionSet1.c, FunctionSet1.h
FunctionSet2.c, FunctionSet2.h
etc.
I thought I could define a structure type in structures.h:
struct type_struct1 {int a,b;}; // define type 'struct type_struct1'
then declare a function1() returning a structure of type type_struct1 in FunctionSet1.h:
#include "structures.h"
struct type_struct1 function1(); // declare function1() that returns a type 'struct type_struct1'
then write function1() in FunctionSet1.c:
#include "FunctionSet1.h"
struct type_struct1 function1() {
struct type_struct1 struct1; // declare struct1 as type 'struct type_struct1'
struct1.a=1;
struct1.b=2;
return struct1;
}
Edit: with the corrected code above, the compiler returns
306 'struct' tag redefined 'type_struct1' structures.h
Is the file set good practice ?
What is the good practice to manage the structures ?
In your example, you declare a structure named type_struct in structure.h, then in FunctionSet1.h the structure that you are returning is type_struct, and in the .c it is called struct1.
So i think that the problem is that struct1 and type_struct are not recognized because they have never been defined ...
However, the organization of your files is fine.
Your general structure looks good. One thing you need to do, as zenith mentioned, is to put include guards into your header files. What that is is a set of #define's that make sure that the contents of the header are not included more that once in a given file. For example:
structures.h:
#ifndef STRUCTURES_H
#define STRUCTURES_H
struct type_struct1{
int a,b;
};
...
// more structs
...
#endif
FunctionSet1.h:
#ifndef FUNCTION_SET_1_H
#define FUNCTION_SET_1_H
#include "structures.h"
struct type_struct1 function1();
...
// more functions in FucntionSet1.c
...
#endif
main.c:
#inlcude <stdio.h>
#include "structures.h"
#include "FunctionSet1.h"
int main(void)
{
struct type_struct1 struct1;
struct1 = function1();
return 0;
}
Here, main.c includes structures.h and FunctionSet1.h, but FunctionSet1.h also includes structures.h. Without the include guards, the contents of structures.h would appear twice in the resulting file after the preprocesser is done. This is probably why you're getting the "tag redefined" error.
The include guards prevent these type of errors from happening. Then you don't have to worry about whether or not a particular header file was included or not. This is particularly important if you're writing a library, where other users may not know the relationship between your header files.
First of all, you have to declare the structure in your file.h (you can use typedef to create an alias)
typedef struct Books
{
char title[50];
int book_id;
} books;
then, you have to include your file.h in your file.c and declare your variable like this
#include "file.h"
int main()
{
books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
or like this if you didn't use typedef
#include "file.h"
int main()
{
struct Books book1;
book1.title = "Harry Potter";
book1.book_id = 54;
}
Thank you all.
I read again what you said and found that the code above is now correct.
The error I report is with testing the following main.c
#include "structures.h"
#include "FunctionSet1.h"
void main() {
struct type_struct1 struct2;
struct2=function1();
}
in which structures.h is included again, thus causing the error. Removing the include eliminates the error.
I will now look into header guards to avoid such problems.
Thanks again.
I'm trying to minimize interdependence of #include files as a general practice.
In xxx.h I have:
struct my_struct; // partial decl to satisfy use of my_struct*
void funct(struct my_struct* ms); // uses the partial def
How to do a similar partial decl with a typedef'd struct?
I have an actual decl in some third #include that looks like (say in yyy.h):
typedef struct my_data_s {
int ival;
... struct's other components ...
} my_data_t;
I just want a representative decl in xxx.h that reference the typedef:
typedef struct my_data_s my_data_t; // actual full decl is elsewhere
void funct2(my_data_t* md);
This attempt causes 'redefinition of typedef my_data_t' error. (Using gcc 4.4.3 / Ubuntu 10.4) Other random search attempts (e.g., add '{}' to typedef) also give errors.
I know the compiler only needs to know that the function requires a pointer, so it seems like this should be possible. So far, found nothing that compiles w/o errors/warnings.
I've looked at the other questions and answers, could not find this problem addressed. Seems like there should be a well-known way to do this(?!) (I know that I can #include yyy.y whenever I #include xxx.h - trying to avoid such dependencies.) Thanks.
Have you tried the simple approach:?
xxx.h
struct my_data_s;
typedef struct my_data_s my_data_t;
yyy.h
#include "decl.h"
struct my_data_s {
int foo;
};
C99 doesn't allow to repeat a typedef, C11 does.
Just do the typedef only once and always have it first:
typedef struct my_data my_data;
There also is no need to chose different names for the struct tag and the typedef identifier.
Here's what our group decided to do. It represents a compromise of several conflicting requirements/desires. I am posting to show another approach, so readers of the post have some variety to choose from. It represents the best answer for our situation.
obj_a_defs.h
// contains the definition
// #include'd only by other .h files
...
#define ... // as needed for struct definition
...
typedef struct obj_a {
...
} obj_a;
obj_a.h
// contains the 'full info' about obj_a: data and behaviors
// #include'd by other .c files
...
#include "obj_a_defs.h"
...
// declares functions that implement
// the behaviors associated with obj_a
obj_a.c
...
#include "obj_a.h"
...
// implementations of functions declared in obj_a.h
obj_b.h
// a 'user' of obj_a that uses obj_a as arg
#include "obj_a_defs.h" // to get the typedef
...
int some_b_funct(obj_a* obja, ...);
...
obj_b.c
// Defines the 'contract' that this implementation
// is meeting.
#include "obj_b.h"
...
// This .c file includes obj_a.h only if it
// uses the functions defined for obj_a.
// If obj_a is used only to 'pass through'
// to other modules, there's no need for
// this include.
#include "obj_a.h" // only if obj_b uses
...
// obj_b's function implementations
Rationale / Conditions
typedef and struct kept together
a .c file that uses obj_X must #include "obj_X.h"
to show that use
avoid .h files including other .h files in general;
only 'defs.h' files are #include'd in .h files.
avoid #include'ing a file just to handle dependencies;
IOW avoid #include'ing obj_a.h just because it's used in obj_b.h
I have a C function that I would like to use in my .y bison file. How do I do that? Where do I put the code for my function?
Thanks
In your .y file you can do something like:
%{
#include "types.h"
#include "interface.h"
void doStuff(void);
%}
Either #includeing a header file or declaring it right there.
This means that if interface.h declared a add_colour and add_colourd function you could do something like this later on:
Colour:
ColourSpace { add_colour($1); }
| STAR ColourSpace { add_colourd($2); }
calling them from witin your generated code.
If you wanted to implement them in that generated code to you could use %% at the end of the file and do something like:
%%
void doStuff() {
// Do some stuff!
}
So you can write "plain old C" inside your .y file too.
yacc doesn't seem to like when my tokens are of a type that I defined.
At the top of my grammar (.y) file in a %{ ... %} block, I include a header file that defines the following structure:
typedef struct _spim_register {
spim_register_type type; /* This is a simple enumeration, already defined */
int number;
} spim_register;
Before my list of rules, I have:
%token AREG
...
%union {
struct _spim_register reg;
}
...
%type <reg> register AREG
I get
error: field ‘reg’ has incomplete type
at the line in the %union clause while trying to compile the code produced by bison. In my %union statement, trying to declare reg by writing spim_register reg; gives the error:
unknown type name ‘spim_register’
It seems like there's something special about %union { ... }, because I'm able to use the data structures from my header file in the actions for the rules.
It would help if my #includes were in the right order...
The answer was, as user786653 hinted, here. I needed to include the header file that defines my custom structure before including the .tab.h file in the .l file.
I met the same problem. Because my *.l file like this:
include "y.tab.h"
include "FP.h"
then, I rewrote it like this:
include "FP.h"
include "y.tab.h"
It works. Thank you very much. #ArIck