@kirisky has joined the channel
@mflatt So for what its worth, treeting the va_list like a pointer seems to cause erratic behavior.
I mean, the bug could be somewhere else, and I’m seeing if I can reduce it down.
But…a.
ya*
@leif What platform are you on?
Nevermind – I see that sizeof(va_list)
is 24 bytes on Mac OS, so it must vary more than I thought, and I must have mangled my experiment before
Thinking about it more, a portable solution seems hopeless without va_list
support in libffi, because the specific representation of a va_list
can affect the way that it’s passed in registers or on the stack. The only idea I have is to define _va_list
in ffi/unsafe
based on the result of (system-library-subpath #f)
– so it would work only for platforms where we’ve specifically tracked down and hard-coded the representation.
@mflatt ya, that sounds about right.
Also I’m on OS X.
I’ll look at the system V ABI specs, if they are at least consistent among different instruction sets we probably do have a chance
Looking at the c99 spec, it requires that va_list be a type.
And if that is the case, it seems like if we make a _va-list type, while we won’t be able to do anything with it in Racket code, it could be passed to C code.
(I’m looking at section 7.15 of the latest draft of the c99 spec.)
(As I don’t have a copy of the actual release.)
@leif Supporting va_list seems painful. Just found the section “Variable Length Arguments” in the SWIG manual. It has the subtitle “The horror. The horror.”
@soegaard2 Not trying support varargs…That would be really hard. :confused:
Just va_list.
Which is doable, as its just another value.
As long as it stays an opaque value to Racket, that is fine.
Trying to mimick va_arg, va_first, etc. or the ...
protocol, that sounds scary.
At least based on what I’ve ascertained at the moment.
Iam clearly conflating those. Aren’t va_list used to deal with variable arguments?
You are correct.
va_list however, can also be passed to another function as a type.
This is used if you, say, want to make a helper function.
Ok. So va_list is also useful in other situations.
int myfunc(const char *str, ...) {
va_list ag;
va_start(ag);
helper(ag);
va_end(ag);
}
int helper(va_list ag) {
...
va_arg(ag);
...
}
Yup
in this case, I want to write helper
In particular…
I want to write helper
that just passes the va_list
to another (C) function.
Because I’m hooking up two libraries.
Through Racket….
Of course, this still isn’t enough to duplicate va_copy, as that’s macro. To do that, we would need to make scheme_va_copy, or something like that.
Which does nothing but call the macro.
Of course, if we do that, it would make sense to do that for va_arg as well.
We couldn’t do va_start
and va_end
though, because that would require supporting vaargs, and ...
, which, as you rightly pointed out, is terrifying.
At least, what it looks like anyway. Perhaps I’m wrong.
Thanks for the example.
Any time. :slightly_smiling_face:
@mflatt worksp/librktio/… vs librktio/… these two directories seem pretty similar. Is one of them deprecated?
There should be a “rktio” directory with the rktio implementation and a “worksp/librktio” directory with MSVC projects
I’m not seeing multiple “librktio” directories
err…ya, I mean worksp/rktio. That makes sense that one is for windows. Thanks.
@mflatt oh wait, no
I do see a worksp/librktio.
racket/racket/src/worksp/librktio
Just to be sure: there should only be one “rktio” and one “librktio” directory; the “librktio” directory should be in “worksp”, and the “rktio” directory should not be in “worksp”
Although that one does look like a visual studio project.
Ah, okay.
That is correct.
So, since windows has src/worksp/libffi
, does that mean it doesn’t use src/foreign
?
OH….
src/worksp/libffi probably is in pace of src/foreign/libffi.
The foreign.c
part of src/foreign
is included directly in libracket
, while src/worksp/libffi
is the project for src/foreign/libffi
Okay
Also, I realized, adding a primitive for va_list is silly, since per the spec, its just an (undefined) struct type.
So it would make a lot more sense to just add a function to the core that calls sizeof
(which I suspect already exists), and then define _va-list in racket.
@leif Is even sizeof(va_list)
useful, since the calling convention can depend on more than the size? For example, long
and double
are often passed differently – though I’ll grant that va_list
is unlikely to be represented as a double
. I still think it’s best to use (system-library-subpath #f)
and hardwire a representation in ffi/unsafe
for various known results.
Ah, fair.
@mflatt Actually, no. Since va_list
is NOT a primitive in C (per the spec), it’ll be handled just like any other struct will.
(Like, the size and field order of the struct is undefined, but the fact that it is a struct is.)
“The type declared is va_list which is an object type suitable for holding information needed by the macros va_start, va_arg, va_end, and va_copy”
“object type” => “struct”?
Even so, I thought the way a struct is passed could depend on its content beyond just its size, but I forget these details
That is how I interpret it. Although I admit I didn’t make the spec so I’m not 100% sure.
Ok. FWIW, I don’t think “object” means “struct” in the C standard
Also ya, it certainly is true that structs are passed differently based on what is in them.
Hmm…okay.
I’ll see if I can find an answer to that. Thanks. :slightly_smiling_face:
@mflatt “object: region of data storage in the execution environment, the contents of which can represent values”
So I guess it could be a primitive.
Just not a macro.