[fpc-pascal] Placing binary data (resources) in object files?

Ewald ewald at yellowcouch.org
Mon Jun 3 18:09:15 CEST 2013


Once upon a time, Anthony Walter said:
> I am trying to come up with an embedded binary resource system and was
> considering placing data in object files when I found this question on
> stack overflow:
>  http://stackoverflow.com/questions/4158900/embedding-resources-in-exe-using-gcc
>
>
> I see that it's possible to directly turn any file into an object file
> and reference the memory of that as a resource in a C program using:
>
> extern char binary_foo_bar_start[];
> extern char binary_foo_bar_end[];
>
> My question, is it possible to link extern char in free pascal in a
> way similar to above? Perhaps something similar to:
>
> var binary_foo_bar_start: pointer; external;
>
> {$L foo.bar.o}
>
> Or some permutation of the above?

You can pass an option directly to the link ( add -k--format=binary
-k<binary files you wish to embed> -k--format=default to the fpc command
line), or you could use objcopy.

These two aproaches aren't very portable though, so it is best you write
a script or something that generates code that contains this file.
Something like this:

===php code begin===
<?php

function ObjCopy($file, $name, $outputname = 0)
{
    $contents = file_get_contents($file);
    $size = strlen($contents);
   
    if ($outputname === 0)
        $outputname = "blob_$name.o";
   
    $invalidsymbolcharacters = array('!', '@', '#', '$', '%', '^', '&',
'*', '(', ')', '_', '+', '-', '=', '[', ']', '{', '}', '\'', '\\', '"',
'|', ';', ':', ',', '.', '/', '<', '>', '?', '`', '~');
    $name = str_replace($invalidsymbolcharacters, '_', $name);

    $data = '';
    for ($cnt=0; $cnt < $size; $cnt++)
        $data.= '0x'.dechex(ord($contents[$cnt])).',';
    $data = substr($data, 0, -1);

    $tmpfile = "#include <cstddef>\n";
    $tmpfile.= "extern \"C\" const size_t _binary_{$name}_size = $size;\n";
    $tmpfile.= "extern \"C\" const char _binary_{$name}_start[] =
{{$data}};\n";
    $tmpfile.= "extern \"C\" const char* _binary_{$name}_end =
&_binary_{$name}_start[0] + $size-1;\n";

    fwrite($handle = popen("gcc -o '$outputname' -c -x c++ - -O3 -Wall
-pipe", 'w'), $tmpfile);
    pclose($handle);
}

?>
===php code end===

Usage: `ObjCopy('binaryinputfile', 'symol name',
'outputobjectfile.o');`. Then add `-koutputobjectfile.o` to the command
line of fpc. Next you can define your symbols in pascal as follows:

{$escapedpascalname}_start: array[0..<$length-1>] of cuint8; external
name '_binary_{$escapedname}_start';
{$escapedpascalname}_end: array[<1-$length>."..0] of cuint8; external
name '_binary_{$escapedname}_end';
{$escapedpascalname}_size: array[0..0] of cuint8; external name
'_binary_{$escapedname}_size';

Where {$escapedpascalname} is the name you gave as the second argument
to the function above. `$length` is the length of the original data in
bytes. To read the size, just use `csize_t(@{$escapedpascalname}_size)`.

Note that the above is a very quick draft (kind of a quickfix for some
other project -- but is works) and thus contains errors and lacks error
checking. Use at your own risk ;-)

PS: Sorry about the php code there; I know it's not the php mailing
list, but my buildtool happens to be written in php ;-)

-- 
Ewald




More information about the fpc-pascal mailing list