1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
121
  
# Developer Documentation 
 
Custom functions are internally represented by `struct Sass_C_Function_Descriptor`. 
 
## Sass_C_Function_Descriptor 
 
```C 
struct Sass_C_Function_Descriptor { 
  const char*      signature; 
  Sass_C_Function  function; 
  void*            cookie; 
}; 
``` 
 
- `signature`: The function declaration, like `foo($bar, $baz:1)` 
- `function`:  Reference to the C function callback 
- `cookie`:    any pointer you want to attach 
 
### signature 
 
The signature defines how the function can be invoked. It also declares which arguments are required and which are optional.  Required arguments will be enforced by LibSass and a Sass error is thrown in the event a call as missing an argument. Optional arguments only need to be present when you want to overwrite the default value. 
 
    foo($bar, $baz: 2) 
 
In this example, `$bar` is required and will error if not passed. `$baz` is optional and the default value of it is 2. A call like `foo(10)` is therefore equal to `foo(10, 2)`, while `foo()` will produce an error. 
 
### function 
 
The callback function needs to be of the following form: 
 
```C 
union Sass_Value* call_sass_function( 
    const union Sass_Value* s_args, 
    void*                   cookie 
) { 
  return sass_clone_value(s_args); 
} 
``` 
 
### cookie 
 
The cookie can hold any pointer you want. In the `perl-libsass` implementation it holds the structure with the reference of the actual registered callback into the perl interpreter. Before that call `perl-libsass` will convert all `Sass_Values` to corresponding perl data types (so they can be used natively inside the perl interpretor). The callback can also return a `Sass_Value`. In `perl-libsass` the actual function returns a perl value, which has to be converted before `libsass` can work with it again! 
 
## Sass_Values 
 
```C 
// allocate memory (copies passed strings) 
union Sass_Value* make_sass_boolean (int val); 
union Sass_Value* make_sass_number  (double val, const char* unit); 
union Sass_Value* make_sass_color   (double r, double g, double b, double a); 
union Sass_Value* make_sass_string  (const char* val); 
union Sass_Value* make_sass_list    (size_t len, enum Sass_Separator sep); 
union Sass_Value* make_sass_map     (size_t len); 
union Sass_Value* make_sass_null    (); 
union Sass_Value* make_sass_error   (const char* msg); 
 
// Make a deep cloned copy of the given sass value 
union Sass_Value* sass_clone_value (const union Sass_Value* val); 
 
// deallocate memory (incl. all copied memory) 
void sass_delete_value (const union Sass_Value* val); 
``` 
 
## Example main.c 
 
```C 
#include <stdio.h> 
#include <stdint.h> 
#include "sass/context.h" 
 
union Sass_Value* call_fn_foo(const union Sass_Value* s_args, void* cookie) 
{ 
  // we actually abuse the void* to store an "int" 
  return sass_make_number((size_t)cookie, "px"); 
} 
 
int main( int argc, const char* argv[] ) 
{ 
 
  // get the input file from first argument or use default 
  const char* input = argc > 1 ? argv[1] : "styles.scss"; 
 
  // create the file context and get all related structs 
  struct Sass_File_Context* file_ctx = sass_make_file_context(input); 
  struct Sass_Context* ctx = sass_file_context_get_context(file_ctx); 
  struct Sass_Options* ctx_opt = sass_context_get_options(ctx); 
 
  // allocate a custom function caller 
  Sass_C_Function_Callback fn_foo = 
    sass_make_function("foo()", call_fn_foo, (void*)42); 
 
  // create list of all custom functions 
  Sass_C_Function_List fn_list = sass_make_function_list(1); 
  sass_function_set_list_entry(fn_list, 0, fn_foo); 
  sass_option_set_c_functions(ctx_opt, fn_list); 
 
  // context is set up, call the compile step now 
  int status = sass_compile_file_context(file_ctx); 
 
  // print the result or the error to the stdout 
  if (status == 0) puts(sass_context_get_output_string(ctx)); 
  else puts(sass_context_get_error_message(ctx)); 
 
  // release allocated memory 
  sass_delete_file_context(file_ctx); 
 
  // exit status 
  return status; 
 
} 
``` 
 
## Compile main.c 
 
```bash 
gcc -c main.c -o main.o 
gcc -o sample main.o -lsass 
echo "foo { margin: foo(); }" > foo.scss 
./sample foo.scss => "foo { margin: 42px }" 
```