call back to LCB from C code?

LiveCode Builder is a language for extending LiveCode's capabilities, creating new object types as Widgets, and libraries that access lower-level APIs in OSes, applications, and DLLs.

Moderators: LCMark, LCfraser

Post Reply
Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

call back to LCB from C code?

Post by Emily-Elizabeth » Sun Mar 08, 2026 8:09 pm

I was wondering if the C code dylib can call back into the LCB?

stam
Posts: 3192
Joined: Sun Jun 04, 2006 9:39 pm

Re: call back to LCB from C code?

Post by stam » Sun Mar 08, 2026 9:26 pm

Emily-Elizabeth wrote:
Sun Mar 08, 2026 8:09 pm
I was wondering if the C code dylib can call back into the LCB?
I really don't know enough about LCB (few here do...)

According to Claude:
Claude AI wrote:Yes, C code in a dylib can call back into LCB, through handler references passed as function pointers.
The mechanism works like this:
On the LCB side, you declare a handler type that matches the C callback signature, then pass an LCB handler as a parameter to the foreign function:

Code: Select all

-- Declare the callback signature
handler type MyCallbackType(in pValue as Integer) returns nothing

-- Declare the foreign function that accepts a callback
foreign handler C_DoSomethingWithCallback(in pCallback as MyCallbackType) \
    returns nothing \
    binds to "c:mylib>DoSomethingWithCallback"

-- Your LCB handler that will be called from C
handler MyCallback(in pValue as Integer)
    -- this runs when C calls back
    log pValue
end handler

-- Wire it up
public handler CallIntoC()
    C_DoSomethingWithCallback(MyCallback)
end handler
On the C side, the dylib receives a plain function pointer it can invoke normally:
ctypedef void (*MyCallbackType)(int value);

void DoSomethingWithCallback(MyCallbackType callback) {
    // Do some work...
    callback(42);  // calls back into LCB
}
Key points to be aware of:

The LCB handler you pass must match the handler type signature exactly
The callback happens synchronously on the same thread — be cautious if your C code calls back from a different thread, as LCB is not thread-safe in that context
If you need asynchronous callbacks (e.g. from a C thread), you'll need to marshal the call back to the main thread, typically by posting a message or using a queue mechanism, which gets considerably more involved
Memory management: the LCB runtime keeps the handler alive as long as the reference exists, but if C holds onto the pointer longer than the LCB side expects, you can get dangling pointer issues

stam
Posts: 3192
Joined: Sun Jun 04, 2006 9:39 pm

Re: call back to LCB from C code?

Post by stam » Sun Mar 08, 2026 9:33 pm

Claude AI wrote: Async callbacks are the tricky case because you cannot call the LCB handler directly from a C thread — it will crash or corrupt state. You need to marshal the call back onto LCB's main thread.
There are two practical approaches:

Option 1: Polling (Simpler)
C side maintains a thread-safe queue. LCB polls it on a timer.

C side:

Code: Select all

#include <pthread.h>
#include <stdlib.h>

// Thread-safe queue
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
static int s_pending_value = 0;
static int s_has_pending = 0;

// Called from background thread
void WorkerThread(void *arg) {
    // ... do async work ...
    int result = 42;
    
    pthread_mutex_lock(&s_mutex);
    s_pending_value = result;
    s_has_pending = 1;
    pthread_mutex_unlock(&s_mutex);
}

// LCB calls this on its timer to drain the queue
int PollForResult(int *out_value) {
    pthread_mutex_lock(&s_mutex);
    int has = s_has_pending;
    if (has) {
        *out_value = s_pending_value;
        s_has_pending = 0;
    }
    pthread_mutex_unlock(&s_mutex);
    return has;
}

LCB side:

Code: Select all

foreign handler C_PollForResult(out pValue as Integer) \
    returns Integer \
    binds to "c:mylib>PollForResult"

handler type MyCallbackType(in pValue as Integer) returns nothing

private variable mCallback as optional MyCallbackType
private variable mTimer as optional Timer

public handler StartAsync(in pCallback as MyCallbackType)
    put pCallback into mCallback
    -- poll every 50ms
    create timer
    set the period of the result to 50
    set the action of the result to MyPollHandler
    put the result into mTimer
end handler

handler MyPollHandler()
    variable tValue as Integer
    if C_PollForResult(tValue) is 1 then
        if mCallback is not nothing then
            mCallback(tValue)
        end if
    end if
end handler


Option 2: MCEngineRunloopScheduleCallback (Cleaner)
The LC engine exposes a function that lets C schedule work onto the main thread's runloop — no polling needed.

C side:

Code: Select all

// Declare the engine's scheduling function
// (available when loaded inside the LC engine process)
typedef void (*MCEngineRunloopCallback)(void *context);
extern void MCEngineRunloopScheduleCallback(
    MCEngineRunloopCallback callback, void *context);

typedef void (*LCBHandlerType)(int value);

typedef struct {
    LCBHandlerType lcb_handler;
    int            value;
} CallbackContext;

// Called on main thread by the engine runloop
static void MainThreadCallback(void *context) {
    CallbackContext *ctx = (CallbackContext *)context;
    ctx->lcb_handler(ctx->value);   // safe — we're on main thread now
    free(ctx);
}

// Called from background thread
void WorkerThread(void *arg) {
    LCBHandlerType handler = (LCBHandlerType)arg;
    
    // ... do async work ...
    int result = 42;
    
    CallbackContext *ctx = malloc(sizeof(CallbackContext));
    ctx->lcb_handler = handler;
    ctx->value       = result;
    
    // Marshal back to main thread
    MCEngineRunloopScheduleCallback(MainThreadCallback, ctx);
}

LCB side:

Code: Select all

handler type MyCallbackType(in pValue as Integer) returns nothing

foreign handler C_StartWorker(in pCallback as MyCallbackType) \
    returns nothing \
    binds to "c:mylib>StartWorker"

public handler StartAsync(in pCallback as MyCallbackType)
    C_StartWorker(pCallback)
    -- no timer needed; engine calls back when ready
end handler


Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

Re: call back to LCB from C code?

Post by Emily-Elizabeth » Sun Mar 08, 2026 9:53 pm

Screenshot 2026-03-08 at 12.17.16.png
My latest creation ;)

Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

Re: call back to LCB from C code?

Post by Emily-Elizabeth » Sun Mar 08, 2026 10:43 pm

stam wrote:
Sun Mar 08, 2026 9:26 pm
I really don't know enough about LCB (few here do...)
I'm still learning, but have a few extensions on my website.

Klaus
Posts: 14309
Joined: Sat Apr 08, 2006 8:41 am
Contact:

Re: call back to LCB from C code?

Post by Klaus » Mon Mar 09, 2026 11:57 am

Dear Emily-Elizabeth,

thank you very much for all of your work, much appreciated! :-)
Looking forward to whatever you will create in the future.

Best

Klaus

P.S.
Does .nf stand for Norfolk Island, south of Australia?

Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

Re: call back to LCB from C code?

Post by Emily-Elizabeth » Mon Mar 09, 2026 12:56 pm

Klaus wrote:
Mon Mar 09, 2026 11:57 am
thank you very much for all of your work, much appreciated! :-)
Looking forward to whatever you will create in the future.
Does .nf stand for Norfolk Island, south of Australia?
Thank you for the kind words. Check out my website for a few goodies that I've already made (just rename the oxtstack to livecodestack).
.NF is the extension code for Norfolk Island.
Seems like it is :) Thanks for teaching me something new! I'm in Canada though, just didn't have many good choices for a free domain name with the host company.

Klaus
Posts: 14309
Joined: Sat Apr 08, 2006 8:41 am
Contact:

Re: call back to LCB from C code?

Post by Klaus » Mon Mar 09, 2026 1:06 pm

Dear Emily-Elizabeth,

of course I already check your site, nice stuff.
Canada not Norfolk Island, OK, get it! :-)

Best

Klaus

Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

Re: call back to LCB from C code?

Post by Emily-Elizabeth » Mon Mar 09, 2026 2:07 pm

Klaus wrote:
Mon Mar 09, 2026 1:06 pm
of course I already check your site, nice stuff.
Aren't you full of kind words this morning :oops:
Klaus wrote:
Mon Mar 09, 2026 1:06 pm
Canada not Norfolk Island, OK, get it! :-)
Yeah, the cold and icy place ;)

Klaus
Posts: 14309
Joined: Sat Apr 08, 2006 8:41 am
Contact:

Re: call back to LCB from C code?

Post by Klaus » Mon Mar 09, 2026 5:18 pm

I'm always full of kind words, kudos goes to my mom! :-)

Emily-Elizabeth
Posts: 157
Joined: Mon Jan 03, 2022 7:10 pm
Contact:

Re: call back to LCB from C code?

Post by Emily-Elizabeth » Mon Mar 09, 2026 5:32 pm

Klaus wrote:
Mon Mar 09, 2026 5:18 pm
I'm always full of kind words, kudos goes to my mom! :-)
aww.. Moms are awesome :D

Post Reply