1

I'm working on part of a C program where a user inputs a network filter string (think Wireshark). A filter string like, for example

(s->field_a == 1 || s->field_c <= 10) && ! (s->field_c % 2)

Is entered by the user and pasted into a function in a temporary file, which is compiled as a shared lib and loaded wit dlopen. The function simply evaluates the string.

Now, the type of "s" struct is defined in some .h file, let's say struct.h. Obviously struct.h won't be available for the runtime compilation. I can just paste its content to a string and fprintf it, but then I'd have to re-paste it whenever I change the header.

I could write a script that'd do it during building, but maybe there's a better option.

Is there a way to "paste" the content of the file as a string using e.g. the preprocessor?

Some code to illustrate what I'm trying to do:

struct.h:

struct example_struct
{
    int field_a;
    int field_b;
    int field_c;
};

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "struct.h"

int main(int argc, char *argv[]) {

    struct example_struct s;

    char filter_string[] = "(s->field_a == 1 || s->field_c <= 10) && ! (s->field_c % 2)"; // what the user can input

    FILE *f = fopen("/tmp/prog.c","w");
    // here I'd like to insert contents of struct.h into f
    fprintf(f, "int filter(struct example_struct * s) {\n");
    fprintf(f, "return (%s);}\n", filter_string);
    fclose(f);

    system("gcc /tmp/prog.c -o /tmp/prog.so -shared -fPIC");

    // load and use function...
}

Edit: I don't need an actual representation as a char[], it can be a string literal.

I'm trying not to use xxd or some other tool before building the program, I can do that fine by inserting the text with a python script or whatever. I'm just curious if a "pure" solution is possible.

AdamTL
  • 170
  • 11
  • 2
    Possible duplicate of ["#include" a text file in a C program as a char\[\]](https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char) (in a more generic way) – Federico klez Culloca Jun 12 '19 at 13:20

3 Answers3

1

Is there a way to "paste" the content of the file as a string using e.g. the preprocessor?

[...]

I'm trying not to use xxd or some other tool before building the program, I can do that fine by inserting the text with a python script or whatever. I'm just curious if a "pure" solution is possible.

The C language does not have a built-in feature for including compile-time file contents as character array contents, whether in string literal form or any other kind of initializer form. If you want that then you need to use some kind of code generator.

But I'd like to challenge your assumptions for a moment. You say,

Obviously struct.h won't be available for the runtime compilation.

, but I don't see why that has to be true. At least in principle, nothing prevents you from packaging the header file together with the program, installing it in a location known to the program (or that the program can discover or be configured for) and using it as a normal header.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Found a trick with defines that'll do it here. It's a bit wacky, but it does exactly what I wanted.

In struct.h:

#ifndef STRINGIFY
#define STRINGIFY(x) x
#endif

STRINGIFY (
struct example_struct
{
    int field_a;
    int field_b;
    int field_c;
}; )
#undef STRINGIFY

That way when it's included as a regular file, the define does nothing. In main.c I can now insert the string as follows:

#define STRINGIFY(x) #x
const char * header_string = 
#include "struct.h"
;
#undef STRINGIFY

Code from "struct.h" will be included as a string literal.

AdamTL
  • 170
  • 11
  • Watch out for commas in the argument to `STRINGIFY`. – rici Jun 12 '19 at 16:02
  • Yeah... it also won't work for defines/includes in the argument from what I can tell – AdamTL Jun 12 '19 at 20:00
  • that, too. The external utility to generate code is really the best solution. You could write your own in a couple of hours if you don't want to rely on `xxd` for whatever reason. – rici Jun 12 '19 at 20:34
0

It is not a language question, but some development systems could help. For example the Windows API has the notion of resource which allows to embed a file in an executable and access that resource as run time more or less as if it were an internal file.

According to those other SO questions:

(and probably others: just follow the possible duplicate links), there are various ways with gcc on Linux from directly using the ld linker, to using external tools like ImageMagick.

But IMHO there is nothing wrong in just including the .h include file into the pack of distributable files that are required to use the application.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252