Difference between revisions of "FPC and Apache Modules"

From Free Pascal wiki
Jump to navigationJump to search
Line 59: Line 59:
 
1 - '''AP_DECLARE'''
 
1 - '''AP_DECLARE'''
  
 +
<pre>
 
AP_DECLARE(void) ap_add_version_component(apr_pool_t *pconf, const char *component);
 
AP_DECLARE(void) ap_add_version_component(apr_pool_t *pconf, const char *component);
  
<pre>
+
 
 
procedure ap_add_version_component(pconf: Papr_pool_t; const component: PChar);
 
procedure ap_add_version_component(pconf: Papr_pool_t; const component: PChar);
 
  {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
 
  {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
Line 69: Line 70:
 
The AP_DECLARE macro says that the calling convention for the function is stdcall on Windows and cdecl on other operating systems, so we need an IFDEF for this. It also says that the function name will have a prefix and a suffix on Windows. The prefix is "_" and the suffix is "@N", where N is a number multiple of 4. Tipically, the number is 4 times the number of parameters on the function, but there are some exceptions. To find out possible conflics on the function names, a software to list all exported functions of a dll was created.
 
The AP_DECLARE macro says that the calling convention for the function is stdcall on Windows and cdecl on other operating systems, so we need an IFDEF for this. It also says that the function name will have a prefix and a suffix on Windows. The prefix is "_" and the suffix is "@N", where N is a number multiple of 4. Tipically, the number is 4 times the number of parameters on the function, but there are some exceptions. To find out possible conflics on the function names, a software to list all exported functions of a dll was created.
  
 +
2 - '''AP_DECLARE_NONSTD'''
 +
 +
<pre>
 +
AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd,
 +
                                                  void *struct_ptr,
 +
                                                  const char *arg);
 +
 +
 +
function ap_set_string_slot(cmd: Pcmd_parms; struct_ptr: Pointer; const arg: PChar): PChar;
 +
cdecl; external LibHTTPD name 'ap_set_string_slot';
 +
</pre>
 +
 +
This is the same as AP_DECLARE, but the calling convention is cdecl and no suffix or preffix is present on the function name.
 +
 +
3 - '''Other combinations'''
 +
 +
<pre>
 +
APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
 +
                                        const char *format, ...)
 +
 +
 +
function apr_file_printf(fptr: Papr_file_t; const format: PChar;
 +
othres: array of const): Integer;
 +
cdecl; external LibAPR name 'apr_file_printf';
 +
</pre>
 +
 +
Another possible combination are macros starting with APR. AP means libhttpd, APR is libapr, APU is libaprutil and API is for libapriconv. Also notice that this function has a variable number of parameters, that in pascal is represented by an array of const.
  
 
==== Possible problems ====
 
==== Possible problems ====

Revision as of 15:05, 14 July 2006

Documentation

How the bindings work

A basic apache module created with Free Pascal will have a code similar to this:

library mod_hello;

{$ifndef win32}
  {$l hello_module.o}
{$endif}

uses httpd;

var
 hello_module: module; {$ifdef Unix}cvar; external; {$endif}
 default_module_ptr: Pmodule;

{$ifdef Win32}
exports
 hello_module name 'hello_module';
{$endif}

begin
  default_module_ptr := @hello_module;
  FillChar(default_module_ptr^, SizeOf(default_module_ptr^), 0);
  with default_module_ptr^ do
  begin
    version := MODULE_MAGIC_NUMBER_MAJOR;
    minor_version := MODULE_MAGIC_NUMBER_MINOR;
    module_index := -1;
    name := 'mod_hello.so';
    magic := MODULE_MAGIC_COOKIE;
  end;
end.

Apache uses a non-standard way to exchange information between the module and the library. Normally libraries export functions, but Apache instead expects a library that exports a variable. The variable is a structure with the module information. This variable needs to be filled with information as soon as the module is loaded.

Now, on Windows we can easely export a variable with Free Pascal. Just put it on the exports section. On Linux, Free Pascal doesn´t yet support exporting variables, so we need a alternative. To work around this we can create a assembler file that will export the variable and then link it into our code.

The file will look like this:

[SECTION .data]
global hello_module
hello_module dd 0

And the command line to compile this assembler code is: "nasm -f elf hello_module.asm"

How the bindings were created

The translated headers follow some simple guidelines. First all translated declarations remain at the exact same position as they were on the .h files, unless there is a incompatibility and they have to be moved. This is to make it easier to compare the .h files with the pascal translation and find possible mistakes on translation. Second, most files become include files, and some units are created to hold them. In particular, one unit was created for each apache library (httpd, apr, aprutil and apriconv).

The Apache headers rely heavely on macros to work. In fact, almost every single declaration is a macro. Bellow are some of the most common macros and appropriate translations:

1 - AP_DECLARE

AP_DECLARE(void) ap_add_version_component(apr_pool_t *pconf, const char *component);


procedure ap_add_version_component(pconf: Papr_pool_t; const component: PChar);
 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
 external LibHTTPD name LibNamePrefix + 'ap_add_version_component' + LibSuff8;

The AP_DECLARE macro says that the calling convention for the function is stdcall on Windows and cdecl on other operating systems, so we need an IFDEF for this. It also says that the function name will have a prefix and a suffix on Windows. The prefix is "_" and the suffix is "@N", where N is a number multiple of 4. Tipically, the number is 4 times the number of parameters on the function, but there are some exceptions. To find out possible conflics on the function names, a software to list all exported functions of a dll was created.

2 - AP_DECLARE_NONSTD

AP_DECLARE_NONSTD(const char *) ap_set_string_slot(cmd_parms *cmd, 
                                                   void *struct_ptr,
                                                   const char *arg);


function ap_set_string_slot(cmd: Pcmd_parms; struct_ptr: Pointer; const arg: PChar): PChar;
 cdecl; external LibHTTPD name 'ap_set_string_slot';

This is the same as AP_DECLARE, but the calling convention is cdecl and no suffix or preffix is present on the function name.

3 - Other combinations

APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, 
                                        const char *format, ...)


function apr_file_printf(fptr: Papr_file_t; const format: PChar;
 othres: array of const): Integer;
 cdecl; external LibAPR name 'apr_file_printf';

Another possible combination are macros starting with APR. AP means libhttpd, APR is libapr, APU is libaprutil and API is for libapriconv. Also notice that this function has a variable number of parameters, that in pascal is represented by an array of const.

Possible problems

1 - Apache expects that the module is compiled specifically for the exact same version as the server. Because we have a single translation for all 2.0.x versions, you can just change the MODULE_MAGIC_NUMBER_MAJOR to what Apache expects and it should work. On the file ap_mmn.inc you can find a list of apache magic numbers for almost all 2.0.x Apache versions.

Screenshot

Authors

Felipe Monteiro de Carvalho

License

Download

Status: Under development

Installation

Hello World Module

CVS

Not yet available.


Bug Reporting

Tests are necessary to verify if all functions and structures are declared properly.

You can post Bug Reports here:

Change Log

Help

Please send help requests to the Free Pascal mailling list.