The :ef-mb-string type is capable of converting between the internal encoding of LispWorks strings (Unicode) and various encodings that may be expected by the foreign code. The encoding on the foreign side is specified by the
:external-format
argument, which takes an External Format specification.. See the
LispWorks User Guide
for a more detailed description of external formats.
Conside a variant of the last example where the returned string contains characters beyond the ASCII range.
#include <string.h>
#include <stdlib.h>
__declspec(dllexport) void __cdecl random_string2(int length, char *string)
{
int ii;
for (ii = 0; ii < length ; ii++)
string[ii] = 225 + rand() % 26;
string[length] = 0;
}
#include <string.h>
#include <stdlib.h>
void random_string2(int length, char *string)
{
int ii;
for (ii = 0; ii < length ; ii++)
string[ii] = 225 + rand() % 26;
string[length] = 0;
}
A foreign function defined like random-string above is inadequate by itself here because the default external format is that for the default C locale, ASCII. This will signal error when it encounters a non-ASCII character code. There are two approaches to handling non-ASCII characters.
1. Pass an appropriate external format, in this case it is Latin-1:
(fli:define-foreign-function (random-string2
"random_string2"
:source)
((length :int)
(return-string (:reference-return
(:ef-mb-string
:limit 256
:external-format :latin-1))))
:result-type nil
:lambda-list (length &aux return-string)
:calling-convention :cdecl)
(random-string2 3)
=>
"òãö"
(random-string2 6)
=>
"óãøççâ"
2. Set the locale, using set-locale. This sets the C locale and switches the FLI to use an appropriate default wherever an external-format argument is accepted.
(fli:define-foreign-function (random-string
"random_string2"
:source)
((length :int)
(return-string (:reference-return
(:ef-mb-string
:limit 256))))
:result-type nil
:lambda-list (length &aux return-string)
:calling-convention :cdecl)
On a Windows system with current Code Page for Western European languages:
(fli:set-locale)
=>
(win32:code-page :id 1252)
On a Unix/Linux system with a Latin-1/ISO8859-1 default locale:
(fli:set-locale)
=>
:latin-1
After the default external-format has been switched:
(random-string 6)
=>
"≤èñçèõ"
If you do not actually wish to set the C locale, you can call
set-locale-encodings which merely switches the FLI to use the specified external formats where an external-format argument is accepted.