<aceluck>
Hi all, quick question - I'm doing some c ffi stuff, and getting back a string pointer, so I use String.from_cstring(p) - which gives me a ref. What I'd like though, is an immutable string. I can't seem to wrap it in recover val either, because the p is not sendable
<aceluck>
(p has to be a ref according to the String api)
<jemc>
aceluck: without knowing anything else about your surrounding code, your best bet is to get the pointer from FFI as a `Pointer[U8] iso` instead of a `Pointer[U8] ref`
<jemc>
an `iso` reference can pass into a `recover` block, and it can be `consume`d to give to the String constructor
<jemc>
that is, with `String.from_cstring(consume p)`
<aceluck>
Even with consume p I get the error iso! is not a subcap of ref
<aceluck>
My mistake... the p was indeed an iso!
<aceluck>
@jemc: Thanks
<aceluck>
I had to get it as Pointer[U8] iso^ so as not to make it an iso!
<aceluck>
It does segfault though :)
<jemc>
ah, sorry about forgetting the `^` part
<aceluck>
Could consuming the p cause the garbage collector to free the pointer? Cause now I'm getting a segmentation fault - but it's not happening straight away
<jemc>
aceluck: the `consume` melts away at compile time, so it wouldn't cause any garbage collection
<jemc>
however, it's definitely possible that some aspect of your FFI pointer managment is going poorly for you
<aceluck>
It works well when I pass p as ref though. But then I have to clone() the string to make it read only. Which is an okay workaround, except that it feels wrong and might impact performance
<jemc>
is it possible that the C library is deallocating the pointer on you?
<jemc>
clone does a copy of the data into a new pointer "owned by Pony"
<jemc>
what call in what C library are you getting your pointer from?
<aceluck>
I'm not storing the ref and passing into the recover block, but sending it without aliasing
<aceluck>
It's libgmp
dtzWill has quit [Ping timeout: 240 seconds]
<jemc>
that shouldn't affect anything related to GC though... :/
<jemc>
in fact the generated code should be pretty much equivalent as you doing the FFI call just outside the recover block and assigning to an iso
<aceluck>
Yeah.... Also, it didn't "do the trick". When I compiled again, I got a segfault. Another recompile, and it was fine, another I got a fault and so on.
jemc has quit [Ping timeout: 260 seconds]
jemc has joined #ponylang
<jemc>
aceluck: I'd suggest trying the other approach for string allocation in the gmp library - supplying your own string
<jemc>
figure out how big of a string to allocate, using the `mpz_sizeinbase (op, base) + 2` method recommended by the gmp docs, then do something like:
<jemc>
that will let you end up with a pointer that is Pony-managed, but without the unnecessary allocate-and-copy
<doublec>
It's possible the segfault is due to some other ffi usage. Your usage in that case does look fine.
<doublec>
I assume Pony uses 'free' to free the String memory
<jemc>
yeah, I suspect that either pattern should be fine, but the pattern I suggested of letting pony allocate the pointer means you won't have to track it and free it yourself later
<aceluck>
Do I then make the string from the buf or the returned pointer?
<jemc>
doublec: no, Pony has its own alloc and free methods that go to a pool
<jemc>
aceluck: the buf is your string already - ignore the returned pointer
<doublec>
jemc: but if the pointer is from ffi it should be free'd when the String object is finalized shouldn't it?
<doublec>
Oh I see - is the reason for the segfault that Pony attempts to free it?
<doublec>
and it was malloc'd instead of using pony_alloc?
<doublec>
the help for from_cstring says to only use it for arrays that were pony_alloc'd
<aceluck>
I have a few attempts in that file - fromBase2 is the one using pony alloc. But the buffer doesn't become the string for some reason. However, if I initialize from the pointer returned, I get a result
<doublec>
aceluck: I think the String needs to be sized as gmpz_sizeinbase + 2
<doublec>
aceluck: to account for sign and null character.
<aceluck>
Ah yes, true. Still same result though :/
<jemc>
aceluck: can you update the gist with your changes?
<doublec>
aceluck: fromBase2 seems to work for me
<doublec>
aceluck: If I uncomment the "let s2" and return "s2"
<jemc>
doublec: but it should be working for returning buf
<aceluck>
Yes, that's what's odd
<doublec>
ah I see
<doublec>
So the constructor for String only reserves the space, the length of the string is still zero
<carado>
hi, i'm trying to build to release branch of ponyc and i get the single error "src/libponyc/type/typeparam.c:606:5: error: this statement may fall through", should i just remove -Werror from the Makefile ?
<carado>
(i've heard bad things about -Werror in release building)
samuell has joined #ponylang
<carado>
(yeah that and specifying CC= worked nevermind)
<shepheb>
in "All functions on a class are actually receivers." I would say methods, not receivers.
<shepheb>
"this" is the receiver, foo() is the method.
<shepheb>
content LGTM
<shepheb>
looks good to me, sorry. I always forget that's mostly a Googlism.
<shepheb>
on another subject, the C FFI parts of the tutorial would perhaps do well to give an example of turning a Pointer[A] from C code into a Pony array.
<autodidaddict>
good points. I'll make some edits. thanks
<shepheb>
it wasn't hard to piece that together from the documentation for arrays, but still.
<shepheb>
(context is getting a void* from SDL_LockTexture that I need to populate)
<autodidaddict>
I figured LGTM was pretty mainstream
<shepheb>
that's what I thought, having seen it myself before joining Google. but then I routinely find people puzzled by it, so I expand it now.
jemc has joined #ponylang
<shepheb>
\o/ my Gameboy emulator is now rendering something.
<shepheb>
it's a bit broken, but it's rendering something.
obadz has quit [Ping timeout: 240 seconds]
obadz has joined #ponylang
<autodidaddict>
that's awesome
<shepheb>
looking forward to sharing this code, but it's not interesting when you get a hollow window frame and can't run any software on it.
<autodidaddict>
those are the inspiring moments... when you know your building blocks are there and working. That's when the fun starts :D
<jemc>
carado: can you file an issue ticket about the fall through warning? we should fix it
<jemc>
shepheb: exciting!
<shepheb>
there, found the rendering bug. it's rendering a really basic scene competently.
<shepheb>
the junk characters aren't intended, but they show up in a released emulator too, so I guess it's a bug in my test app.
<shepheb>
next is running a test app that exercises the CPU, and looking for any bugs.
amclain has joined #ponylang
<autodidaddict>
nice
aceluck has joined #ponylang
obadz has quit [Ping timeout: 246 seconds]
obadz has joined #ponylang
samuell has quit [Quit: Hejdå]
papey_lap has joined #ponylang
papey has quit [Ping timeout: 268 seconds]
bimawa has quit [Quit: WeeChat 1.4]
<aceluck>
Hi - I'm doing some ffi stuff, and it's crashing, and I'm trying to narrow it down. However, scattering print statements throughout the code doesn't work when the output streams are async. Is there a way to do synchronous output?
<jemc>
aceluck: check out the `debug` package, which provides a `Debug` primitive that wraps a synchronous C call to print a debug statement
<aceluck>
Thanks
<jemc>
it's cheating on the ambient authority principle a bit, but it's only present in `--debug` builds, and it's really darn useful
<aceluck>
I'll only use it temporarily, promise ;)
<aceluck>
Doing ffi - if I need to pass a **void so that I can get back a pointer to some opaque structure - do I pass in addressof a Pointer[U8] or..?
<jemc>
yeah, I'd probably do `addressof` on a `Pointer[None]`
<jemc>
IIRC there's also another trick where for an opaque object you can make a `class` with no fields, and use that instead of the `Pointer[None]`
<aceluck>
Okay cool
<jemc>
let me make sure I'm remembering that right though
<jemc>
ah, not quite right
<jemc>
the idea was to make a primitive, and use `Pointer[MyPrimitive]` instead of `Pointer[None]`
<aceluck>
Hmm... it needs to be dynamic though
<jemc>
aceluck: it still can be - you never unwrap the pointer
<aceluck>
Primitive works fine if there's only one I suppose
<aceluck>
... not sure I follow
<jemc>
you're not using it like a real primitive, you're just using it as a type system trick so you can distinguish one FFI pointer type from another
<aceluck>
Found my segfault - I'd passed None instead of Pointer[None] somewhere I meant to pass a nullpointer
<jemc>
yeah, debugging FFI usage can be tricky - in any otherwise memory-safe language, not just Pony
<jemc>
that's one big reason to want to isolate your FFI usage to just a handful of packages that wrap the FFI interface in an idiomatic Pony one
<aceluck>
Indeed. Ironically, I started using pony to avoid that kind of trouble :)
<jemc>
sounds like it's time to start on your libgmp port then :D
<aceluck>
But yes, once it's wrapped up nicely, it'll be sweet
autodidaddict has quit [Ping timeout: 260 seconds]
papey_lap has quit [Ping timeout: 240 seconds]
<aceluck>
Why does Array.from_cpointer require a ref to the pointer?
<jemc>
aceluck: because the `Array` it creates is also a `ref`
<aceluck>
How do I make a read only copy of an array?
<aceluck>
I keep banging my head here. from_cpointer requires a ref, so the resulting array is a ref. If I copy it, copy_to also needs a ref. There's no way to get from ref to val, because I can't recover the original pointer. Argh
<jemc>
aceluck: I think you need the same pattern I suggested yesterday - if you use an `iso` for the original pointer, it can pass into the `recover` block (because it is sendable), and from there you can consume it to "drop down" to `ref` for the argument of `Array.from_cpointer`