Make ANSI Common Lisp available on Haiku (again)

the pthreqd library exposes a C API that is compatible to what other systems have. The fact that some of it is implemented in C++ (if any actually is) should not be a problem here.

I suspect you are looking at the wrong place by blaming C++ for the problem.

The only thing that changes between C and C++ is the way function names are converted to symbols in the executable.

For example consider a C function

int foo(int a, int b);

The symbol name will be “foo”.

Now consider these C++ functions. Note that in C++, several function can exist with the same name, but different parameters:

int foo(int a, int b);
int foo(int a, const char* b);

So, the C++ convert the function names in a way that also encodes the parameter. In this case:

_Z3fooii // _Z for a function, 3 for the name length, "foo", then two 'i' indicating that the parameters are int
_Z3fooiPKc // Starts the same, then one i for the first parameter, and PKc (pointer const char) for the second parameter

This is the only difference between C and C++ once the code is compiled. Indeed, if you declare a function named _Z3fooii in C and call it, the linker will find the C++ one. Or if you want to force one C++ function to use the C naming convention, you use extern “C” in the C++ code.

That’s all extern “C” does. Structure layouts are exactly the same between the two languages.

So if your layout is wrong, the problem comes from elsewhere. Maybe SBCL developpers hardcoded the layout of some structure by looking at how it is on another operating system, and in our case that structure has more or less fields, or in a different order. Maybe they are trying to generate such structure layouts by parsing our .h files and doing that incorrectly. Maybe some other problem, but in any case, C++ is not involved there.

2 Likes

C++ has slightly different calling standard. I found out about this when calling C++ functions from Rust. There’s a bindgen utility that can figure out the name mangling, but in the version I was using didn’t know about other details. Where I ran into it, was structs that in C would pass by value or be function return values, but C++ will use pointers. Vaguely recall this applies to structs with destructors, but don’t count on me to be right about that. You can check this with a test program in C that calls into a C++ module. If the foreign function can’t return the type as a function return, it will expect to see a pointer to allocated space as the first parameter.

It’s kind of unlikely that this is your issue, but FYI. As I think PulkoMandy is saying, if you have C API, it doesn’t matter that there’s C++ underneath. This is a problem that can come up only when calling a C++ API.

C++ has a standardized definition of what a struct or class can or cannot contain so that it is compatible with C ABI. It was called “plain old data” types in past versions of the standard but in current one I think they split it into several less constrained cases. Having a destructor definitely doesn’t fit there (the C code wouldn’t know how to call the destructor), but still, I’m sure you could interface that with C code if you wanted to.

@PulkoMandy, in no way I blame C++. This is the issue of List-to-C gluing mechanism.

As per SBCL manual (SBCL 2.5.11 User Manual), foreign function interface is supposed to interact with C code. And you are right, pthread has C API.

@donn, what was your approach in debugging FFI in Rust?

My idea is to try to write a simple C object and some Lisp program to execute it. Then to increase the complexity until I can get to some reproducible problem. Maybe some existing SBCL test is a good starting point.

P.S. Previously I was under impression sb-grovel contributed module is used for FFI in SBCL. Now, I see it uses its own mechanism for interaction in internal sb-alien package.

Sure, it all depends on your FFI and the interface pieces. Some of the time it was about starting with the full Rust module, and simplifying it to isolate the problem.

1 Like