Ring CFFI — Call C Libraries Directly from Ring

111 views
Skip to first unread message

Youssef Saeed

unread,
Apr 9, 2026, 3:26:01 PMApr 9
to The Ring Programming Language
Hello everyone,

I'm excited to announce the release of Ring CFFI — a powerful Foreign Function Interface library for the Ring programming language!

Built on libffi, Ring CFFI allows you to call C functions, manipulate C memory, work with structs/unions/enums, and pass Ring functions as C callbacks — all directly from Ring, without writing any C extension code.

Key Features:
  • Dynamic Library Loading: Load shared libraries (.so, .dll, .dylib) at runtime
  • C Function Calls: Call C functions directly from Ring with automatic type conversion
  • Pointer Operations: Pointer arithmetic, dereferencing, read/write access
  • Struct Support: Define and manipulate C structs with named field access
  • Union & Enum Support: Define and use C unions and enumerations
  • Callbacks: Pass Ring functions as C callbacks
  • Memory Management: Allocate and manage C memory directly
  • C String Handling: Seamless conversion between Ring and C strings
  • Cross-Platform: Works on Windows, Linux, macOS, and FreeBSD
  • High-Level OOP API: Clean FFI class with intuitive method names
Code Example:

Calling C functions from Ring is straightforward:

load "cffi.ring"

new FFI("libc.so.6") { # or msvcrt.dll on Windows
oPrintf = varFunc("printf", "int", ["string"])
varcall(oPrintf, ["Hello from Ring! Value: %d", 42])
}

You can also define and use C structs:

load "cffi.ring"

new FFI {
# Define a Point struct
point = defineStruct("Point", [
:x = "int",
:y = "int"
])

# Allocate and set fields
pPoint = structNew(point)
ptrSet(fieldPtr(pPoint, point, :x), "int", 10)
ptrSet(fieldPtr(pPoint, point, :y), "int", 20)

# Read fields
? "x = " + ptrGet(field(pPoint, point, :x), "int") # 10
? "y = " + ptrGet(field(pPoint, point, :y), "int") # 20
}

Installation

Install easily via RingPM:

ringpm install ring-cffi from ysdragon

Learn MoreNote: Ring CFFI is currently in beta. The API may change as the library evolves. Your testing and feedback are especially valuable at this stage!

Contributions are welcome!

Have ideas or found a bug? Please open an issue or submit a pull request on GitHub.

Your feedback is greatly appreciated!

Hope you find Ring CFFI useful!

Best regards,
Youssef

Mahmoud Fayed

unread,
Apr 9, 2026, 4:21:13 PMApr 9
to The Ring Programming Language
Hello Youssef

This is a very useful and important extension

Thanks for the development & sharing :D

Greetings,
Mahmoud

Bert Mariani

unread,
Apr 9, 2026, 4:52:54 PMApr 9
to The Ring Programming Language
Hello Youssef the Dragon

This is Tremendous with a Capital "T"
This will add some Fire Breathing performance to our Code !!

Best Regards
Bert Mariani

Youssef Saeed

unread,
Apr 9, 2026, 4:59:45 PMApr 9
to The Ring Programming Language
Hello Mahmoud,

Thank you very much for your kind words!

Best regards,
Youssef

Youssef Saeed

unread,
Apr 9, 2026, 5:11:01 PMApr 9
to The Ring Programming Language
Hello Bert,

Thank you for the "Tremendous" response! I love the "Fire Breathing" analogy—unlocking that level of performance seamlessly is exactly what I was aiming for with Ring CFFI.

Please feel free to share your feedback or any "fire" you create once you have the chance to try it out!

Best regards,
Youssef

Mahmoud Fayed

unread,
Apr 10, 2026, 7:24:00 AMApr 10
to The Ring Programming Language
Hello Youssef

You are welcome :D

Greetings,
Mahmoud

Mansour Ayouni

unread,
Apr 10, 2026, 8:04:34 AMApr 10
to Mahmoud Fayed, The Ring Programming Language
Hello Youssef,

I tested all the 23 test examples and they all work.

Is this output correct (I'm on Windows):
image.png

All the best,
Mansour

--

---
You received this message because you are subscribed to the Google Groups "The Ring Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ring-lang+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/ring-lang/1079bff2-0c78-4e9b-81c0-a12bd693664en%40googlegroups.com.

Youssef Saeed

unread,
Apr 10, 2026, 10:06:34 AMApr 10
to The Ring Programming Language
Hello Mansour,

Thank you for the feedback and for testing all 23 examples!

The output you're seeing (Parsed 0 definitions) was indeed a bug in the C Definition Parser (cffi_cdef). It has been fixed in the latest commit.

Please run:
  1. ringpm remove ring-cffi
  2. ringpm install ring-cffi
Then test example 13 again — it should now correctly report the number of parsed definitions.

Best regards,
Youssef

Bert Mariani

unread,
Apr 22, 2026, 4:51:00 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Youssef, Mahmoud  et ALL

Attached: combo for CFFI
     Queens-N.ring
     nqueens_solver.c

423 X Faster than pure Ring version

===========================================
Results:  CFFI Version
C:\MyStuff\AA-Queens-CFFI>ring.exe Queens-N.ring
Enter value of n : 12
Counting N-Queens solutions for n = 12 ...
Total solutions : 14200
End   millisec  : 2792
Start millisec  : 2695
Total millisec  : 97
Total seconds   : 0.10

===========================
Results: Ring code version

Enter value of n : 12
Possible placements are :

End   millisec: 44639
Start millisec: 3617
Total millisec: 41022
Total Seconds : 41.02
Exiting of the program...
Enter to Exit :


// ===========================================
// SETUP (one-time):
//   1. ringpm install ring-cffi from ysdragon   (already done)
//   2. Compile the C solver DLL in this same folder:
//        A.  gcc -O2 -shared -o nqueens.dll nqueens_solver.c
//        --------------------------------------------------------
//        B.  Use Visual Studio 2026 - 64 Bit
//
// The full working setup for anyone to replicate:
// # 1. Install ring-cffi
//   ringpm install ring-cffi from ysdragon
//
// # 2. Set up MSVC (64-bit)
//   call C:\ring\language\build\locatevc.bat x64
//
// # 3. Create the export definition
//   echo EXPORTS > nqueens.def
//   echo nqueens_count >> nqueens.def
//
// # 4. Compile the DLL
//   cl /O2 /LD nqueens_solver.c /Fe:nqueens.dll /link /DEF:nqueens.def
//
// # 5. Run
//   ring.exe Queens-N.ring
//==========================================

FILES generated
 nqueens.def
 nqueens.dll
 nqueens.exp
 nqueens.lib
 nqueens_solver.c
 nqueens_solver.obj
 Queens-N.ring

=============================

Regards
Bert Marini

nqueens_solver.c
Queens-N.ring

Mahmoud Fayed

unread,
Apr 22, 2026, 5:15:52 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Bert

Thanks for sharing

>> "Results:  CFFI Version"

This version is not attached, please attach it.

Greetings,
Mahmoud

Bert Mariani

unread,
Apr 22, 2026, 5:40:33 PM (2 days ago) Apr 22
to The Ring Programming Language
Sorry this is the CFFI version

Attached
     Queens-N.ring         (71 lines )
     nqueens_solver.c   (59 lines )

================================
================================

// Queens-N.ring  (ring-cffi accelerated version)
// Bert Mariani with Claude AI assistance
// 2026-04-22
//
// The hot N-Queens backtracking logic runs entirely in C via ring-cffi.
// Ring handles user I/O and timing only.
//
// ---------------------------------------------------------------

// SETUP (one-time):
//   1. ringpm install ring-cffi from ysdragon   (already done)
//   2. Compile the C solver DLL in this same folder:
//        A.  gcc -O2 -shared -o nqueens.dll nqueens_solver.c
//        --------------------------------------------------------
//        B.  Use Visual Studio 2026 - 64 Bit
//
// The full working setup for anyone to replicate:
// # 1. Install ring-cffi
// ringpm install ring-cffi from ysdragon
//
// # 2. Set up MSVC (64-bit)
//   call C:\ring\language\build\locatevc.bat x64
//
// # 3. Create the export definition
//   echo EXPORTS > nqueens.def
//   echo nqueens_count >> nqueens.def
//
// # 4. Compile the DLL
//   cl /O2 /LD nqueens_solver.c /Fe:nqueens.dll /link /DEF:nqueens.def
//
// # 5. Run
//   ring.exe Queens-N.ring
//==========================================

load "cffi.ring"

// --------------- load the shared C library ----------------------
oFfi = new FFI("nqueens.dll")

// Wrap the one C function we need:
//   long nqueens_count(int n)
oNQueens = oFfi.cFunc("nqueens_count", "int", ["int"])

// --------------- user input -------------------------------------
See "Enter value of n : "
Give n
n = 0 + n

See "Counting N-Queens solutions for n = " + n + " ..." + nl

// --------------- timed solve via C FFI --------------------------
start_t = clock()

    nSolutions = oFfi.invoke(oNQueens, [n])   // runs in compiled C

end_t   = clock()
total_t = end_t - start_t

// --------------- results ----------------------------------------
See nl
See "Total solutions : " + nSolutions + nl
See nl
See "End   millisec  : " + end_t   + nl
See "Start millisec  : " + start_t + nl
See "Total millisec  : " + total_t + nl

timeF = total_t / ClocksPerSecond()
See "Total seconds   : " + timeF   + nl

See nl + "Exiting of the program..." + nl
See "Enter to Exit : "
Give m

=====================================
=====================================
=====================================

/*
 * nqueens_solver.c
 * Fast N-Queens solver written in C.
 * Compile as a shared library for use with ring-cffi.
 *
 * Linux/macOS:
 *   gcc -O2 -shared -fPIC -o libnqueens.so nqueens_solver.c
 * Windows:
 *   gcc -O2 -shared -o nqueens.dll nqueens_solver.c
 */

#include <stdlib.h>
#include <string.h>

static int  *col;        /* column of queen in row i       */
static long  solution_count;

/* Inline safe absolute-value to avoid math.h dependency */
static inline int iabs(int v) { return v < 0 ? -v : v; }

/* Returns 1 if placing a queen at column i in row k is safe */
static int place(int k, int i) {
    int j;
    for (j = 0; j < k; j++) {
        if (col[j] == i || iabs(col[j] - i) == iabs(j - k))
            return 0;
    }
    return 1;
}

/* Recursive backtracking solver (0-based rows) */
static void solve(int k, int n) {
    int i;
    for (i = 0; i < n; i++) {
        if (place(k, i)) {
            col[k] = i;
            if (k == n - 1)
                solution_count++;
            else
                solve(k + 1, n);
        }
    }
}

/*
 * nqueens_count(n)
 *   Returns the total number of solutions for an n×n board.
 *   Exported for ring-cffi to call directly.
 */
long nqueens_count(int n) {
    if (n <= 0) return 0;
    col = (int *)malloc(n * sizeof(int));
    if (!col) return -1;
    solution_count = 0;
    solve(0, n);
    free(col);
    col = NULL;
    return solution_count;
}

============================
============================
============================
Queens-N.ring
nqueens_solver.c

Mahmoud Fayed

unread,
Apr 22, 2026, 5:44:11 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Bert

Thank you very much for sharing :D
This is a beautiful example about using C code and RingCFFI

By the way, attached: Fast N-Queens using Bitmask Backtracking
Written 100% in Ring and finish execution in around 1 second for (n=12)

Enter N: 12
Total solutions: 14200
Time (ms): 1123
Time (sec): 1.12

Time for other values

Enter N: 13
Total solutions: 73712
Time (ms): 6171
Time (sec): 6.17

Enter N: 14
Total solutions: 365596
Time (ms): 36016
Time (sec): 36.02

Greetings,
Mahmoud
nqueens_bitmask_backtracking.ring

Youssef Saeed

unread,
Apr 22, 2026, 8:08:20 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Bert,

Thank you so much for putting this fantastic example together!

A 423x speedup is an incredible real-world demonstration of what RingCFFI was designed for. I truly appreciate you creating such a clear and powerful benchmark.

Best regards,
Youssef

Youssef Saeed

unread,
Apr 22, 2026, 8:09:03 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Mahmoud,

Thank you for sharing your bitmask implementation!

Best regards,
Youssef

Mahmoud Fayed

unread,
Apr 22, 2026, 8:29:28 PM (2 days ago) Apr 22
to The Ring Programming Language
Hello Youssef

You are welcome :D

Greetings,
Mahmoud

Bert Mariani

unread,
Apr 23, 2026, 10:51:56 AM (24 hours ago) Apr 23
to The Ring Programming Language
Hello Youssef, Mahmoud et ALL

The Bit Mask solution is quicker than the Back Tracker
Would you believe 5860 X faster than the Ring-Original

Attached
     Queens-N.ring         -- no change
     nqueens_solver.c    -- Bit Mask version

CFFI Bit Mask:                   7 msec   5860 X      160 X
CFFI Back Tracker:         97 msec     423 X        14 X   
Ring-Bit Mask:            1123 msec       36 X          1 X
Ring-Original         :  41022 msec          1 X

==============================
C:\MyStuff\AA-Queens-CFFI>ring.exe Queens-N.ring
Enter value of n : 12
Counting N-Queens solutions for n = 12 ...
Total solutions : 14200
End   millisec  : 3025
Start millisec  : 3018
Total millisec  : 7         <<<===
Total seconds   : 0.01

Exiting of the program...

==============================
Different Approach

___________________Old (backtracking)___________________New (bitmask)

Conflict check   Loop over all previous queens       Zero — bitmasks do it instantly
Memory   malloc array of columns       None — 3 integers on the stack
Operations per step   O(k) comparisons       2 bitwise ops (&, ~)
Expected speedup   baseline      ~3–5× faster

============================
============================
// Queens-N.ring  (ring-cffi accelerated version)
//  nqueens_solver.c  -  Bitmask backtracking N-Queens solver

#ifdef _MSC_VER
  #define EXPORT __declspec(dllexport)
#else
  #define EXPORT
#endif

static long solution_count;

/*
 * backtrack(colMask, diag1, diag2, all)
 *   Direct C translation of the Ring bitmask backtrack() function.
 */
static void backtrack(unsigned int colMask,
                      unsigned int diag1,
                      unsigned int diag2,
                      unsigned int all)
{
    unsigned int free_bits, bit;

    /* colMask == all means every column has a queen -> solution */
    if (colMask == all) {
        solution_count++;
        return;
    }

    /* available positions: free columns with no diagonal conflict */
    free_bits = all & ~(colMask | diag1 | diag2);

    while (free_bits) {
        /* pick the lowest set bit */
        bit = free_bits & (-(int)free_bits);

        /* remove this bit from free_bits */
        free_bits -= bit;

        /* recurse with updated column and diagonal masks */
        backtrack(
            colMask | bit,
            (diag1  | bit) << 1,
            (diag2  | bit) >> 1,
            all
        );
    }
}

/*
 * nqueens_count(n)
 *   Returns the total number of solutions for an n x n board.
 *   Called from Ring via ring-cffi.
 */
EXPORT long nqueens_count(int n)
{
    unsigned int all;

    if (n <= 0 || n > 31) return 0;

    all = (1u << n) - 1u;   /* n bits set, same as Ring: (1 << n) - 1 */

    solution_count = 0;
    backtrack(0, 0, 0, all);

    return solution_count;
}


=============================

Regards
Bert Mariani
Queens-N.ring
nqueens_solver.c

Mahmoud Fayed

unread,
Apr 23, 2026, 11:00:55 AM (24 hours ago) Apr 23
to The Ring Programming Language
Hello Bert

>> "The Bit Mask solution is quicker than the Back Tracker"
>> "Would you believe 5860 X faster than the Ring-Original"

Thanks for sharing the updated code & benchmarks

Greetings,
Mahmoud
Reply all
Reply to author
Forward
0 new messages