You are on page 1of 10

Ring Documentation, Release 1.5.

void ring_list_addint ( List *pList,int x ) ;


void ring_list_setpointer ( List *pList, int index ,void *pValue ) ;
void ring_list_addpointer ( List *pList,void *pValue ) ;
void ring_list_setfuncpointer ( List *pList, int index ,void (*pFunc)(void *) ) ;
void ring_list_addfuncpointer ( List *pList,void (*pFunc)(void *) ) ;
int ring_list_isfuncpointer ( List *pList, int index ) ;
void ring_list_setdouble ( List *pList, int index ,double number ) ;
void ring_list_adddouble ( List *pList,double x ) ;
void ring_list_setstring ( List *pList, int index ,const char *str ) ;
void ring_list_setstring2 ( List *pList, int index ,const char *str,int nStrSize ) ;
void ring_list_addstring ( List *pList,const char *str ) ;
void ring_list_addstring2 ( List *pList,const char *str,int nStrSize ) ;
List * ring_list_newlist ( List *pList ) ;
List * ring_list_getlist ( List *pList, int index ) ;
void ring_list_setlist ( List *pList, int index ) ;
void ring_list_setactiveitem ( List *pList, Items *pItems, int index ) ;
void ring_list_copy ( List *pNewList, List *pList ) ;
int ring_list_isnumber ( List *pList, int index ) ;
int ring_list_isstring ( List *pList, int index ) ;
int ring_list_islist ( List *pList, int index ) ;
int ring_list_ispointer ( List *pList, int index ) ;
void ring_list_deleteallitems ( List *pList ) ;
void ring_list_insertitem ( List *pList,int x ) ;
void ring_list_insertint ( List *pList,int nPos,int x ) ;
void ring_list_insertdouble ( List *pList,int nPos,double x ) ;
void ring_list_insertpointer ( List *pList,int nPos,void *pValue ) ;
void ring_list_insertstring ( List *pList,int nPos,const char *str ) ;
void ring_list_insertstring2 ( List *pList,int nPos,const char *str,int nStrSize ) ;
void ring_list_insertfuncpointer ( List *pList,int nPos,void (*pFunc)(void *) ) ;
List * ring_list_insertlist ( List *pList,int nPos ) ;
int ring_list_isiteminsidelist ( List *pList,Item *pItem ) ;
int ring_list_findstring ( List *pList,const char *str,int nColumn ) ;
int ring_list_finddouble ( List *pList,double nNum1,int nColumn ) ;
void ring_list_sortnum ( List *pList,int left,int right,int nColumn ) ;
void ring_list_sortstr ( List *pList,int left,int right,int nColumn ) ;
int ring_list_binarysearchnum ( List *pList,double nNum1,int nColumn ) ;
int ring_list_binarysearchstr ( List *pList,const char *cFind,int nColumn ) ;
void ring_list_swap ( List *pList,int x,int y ) ;
double ring_list_getdoublecolumn ( List *pList,int nIndex,int nColumn ) ;
char * ring_list_getstringcolumn ( List *pList,int nIndex,int nColumn ) ;
void ring_list_genarray ( List *pList ) ;
void ring_list_deletearray ( List *pList ) ;
void ring_list_genhashtable ( List *pList ) ;
void ring_list_genhashtable2 ( List *pList ) ;
void ring_list_refcopy ( List *pNewList, List *pList ) ;
void ring_list_clear ( List *pList ) ;
/* Macro */
ring_list_isdouble(pList,index)
ring_list_isint(pList,index)
ring_list_deletelastitem(x)
ring_list_gethashtable(x)
ring_list_getint(pList,index)
ring_list_getpointer(pList,index)
ring_list_getfuncpointer(pList,index)
ring_list_callfuncpointer(pList,index,x)
ring_list_getdouble(pList,index)
ring_list_getstring(pList,index)
ring_list_getstringobject(pList,index)

68.13. Ring API - List Functions 735


Ring Documentation, Release 1.5.1

ring_list_getstringsize(pList,index)
ring_list_getsize(x) (x->nSize)

68.14 Ring API - String Functions

In this section we will learn about the string functions provided by the Ring API to create new string and manipulate
the string content.
String * ring_string_new ( const char *str ) ;
String * ring_string_new2 ( const char *str,int nStrSize ) ;
String * ring_string_delete ( String *pString ) ;
int ring_string_size ( String *pString ) ;
void ring_string_set ( String *pString,const char *str ) ;
void ring_string_set2 ( String *pString,const char *str,int nStrSize ) ;
void ring_string_add ( String *pString,const char *str ) ;
void ring_string_add2 ( String *pString,const char *str,int nStrSize ) ;
void ring_string_print ( String *pString ) ;
void ring_string_setfromint ( String *pString,int x ) ;
char * ring_string_lower ( char *cStr ) ;
char * ring_string_upper ( char *cStr ) ;
char * ring_string_lower2 ( char *cStr,int nStrSize ) ;
char * ring_string_upper2 ( char *cStr,int nStrSize ) ;
char * ring_string_find ( char *cStr1,char *cStr2 ) ;
char * ring_string_find2 ( char *cStr1,int nStrSize1,char *cStr2,int nStrSize2 ) ;
/* Macro */
ring_string_tolower(x)
ring_string_toupper(x)
ring_string_get(x)

68.15 MySQL_Columns() Function Implementation

The next code presents the MySQL_Columns() function implementation.


This function returns table columns information.
void ring_vm_mysql_columns ( void *pPointer )
{
MYSQL *con ;
MYSQL_RES *result ;
int nColumns,x ;
MYSQL_ROW row ;
MYSQL_FIELD *field ;
List *pList, *pList2 ;
if ( RING_API_PARACOUNT != 1 ) {
RING_API_ERROR(RING_API_MISS1PARA);
return ;
}
if ( RING_API_ISPOINTER(1) ) {
con = (MYSQL *) RING_API_GETCPOINTER(1,RING_VM_POINTER_MYSQL) ;
if ( con == NULL ) {
return ;
}
result = mysql_store_result(con);
if ( result == NULL ) {

68.14. Ring API - String Functions 736


Ring Documentation, Release 1.5.1

RING_API_RETNUMBER(0);
return ;
}
pList = RING_API_NEWLIST ;
nColumns = mysql_num_fields(result);
if ( row = mysql_fetch_row(result) ) {
while ( field = mysql_fetch_field(result) ) {
pList2 = ring_list_newlist(pList);
ring_list_addstring(pList2,field->name);
ring_list_adddouble(pList2,field->length);
ring_list_adddouble(pList2,field->type);
ring_list_adddouble(pList2,field->flags);
}
}
mysql_free_result(result);
RING_API_RETLIST(pList);
} else {
RING_API_ERROR(RING_API_BADPARATYPE);
}
}

Lists are of type List, in the previoud function we declared two pointers of type List using List *pList, *pList2;

Note: The function uses RING_API_NEWLIST to create new list instead of ring_list_new() to create the list in
Temp. Memory related to the function scope. This way we can return the list from the function. Also we dont delete
the list, if its stored in a variable by Ring Code it will be saved, if not it will be automatically deleted by RingVM.

The list can contains sub lists, we used the function ring_list_newlist() to create a sublist.
The function ring_list_addstring() is used to add string items to the list/sublist.
The function ring_list_adddouble() is used to add numeric items to the list/sublist.

Note: All numeric items in lists returned from RingVM extension functions must be of type double and added to the
list using ring_list_adddouble() function.

We return the list from the extension function using the RING_API_RETLIST() function.

68.16 Dynamic/Shared Libraries (DLL/So) and LoadLib() function

Instead of rebuilding the RingVM after writing new functions using C/C++ and the Ring API, we can create a DLL/So
file and dynamically use the functions provided by this file in the runtime using the LoadLib() function.
Dynamic library example in C
#include "ring.h"

RING_DLL __declspec(dllexport)

RING_FUNC(ring_ringlib_dlfunc)
{
printf("Message from dlfunc");
}

RING_DLL void ringlib_init(RingState *pRingState)


{

68.16. Dynamic/Shared Libraries (DLL/So) and LoadLib() function 737


Ring Documentation, Release 1.5.1

ring_vm_funcregister("dlfunc",ring_ringlib_dlfunc);
}

the idea is to create the ringlib_init() function, this function will be called by the RingVM when we use the generated
DLL file though the LoadLib() function.
Inside the ringlib_init() function we can register the module function or call a function that do the registration process
for all of the module functions.
The next Ring code demonstrates how to use the DLL library during the runtime.
See "Dynamic DLL" + NL
LoadLib("ringlib.dll")
dlfunc()

Output:
Dynamic DLL
Message from dlfunc

68.16. Dynamic/Shared Libraries (DLL/So) and LoadLib() function 738


CHAPTER

SIXTYNINE

EMBEDDING RING LANGUAGE IN C/C++ PROGRAMS

We can use the Ring language from C/C++ programs using the next functions
RingState *ring_state_init();
ring_state_runcode(RingState *pState,const char *cCode);
ring_state_delete(RingState *pState);

69.1 Ring State

The idea is to use the ring_state_init() to create new state for the Ring Language then call the ring_state_runcode()
function to execut Ring code using the same state. When we are done, we call the ring_state_delete() to free the
memory.
Example:
#include "ring.h"
#include "stdlib.h"
int main(int argc, char *argv[])
{
RingState *pState = ring_state_init();
printf("welcome\n");
ring_state_runcode(pState,"see 'hello world from the ring programming language'+nl");
ring_state_delete(pState);
}

Output:
welcome
hello world from the ring programming language

69.2 Ring State Functions

The Ring API comes with the next functions to create and delete the state. Also we have functions to create new
variables and get variables values.
RingState * ring_state_init ( void ) ;
RingState * ring_state_delete ( RingState *pRingState ) ;
void ring_state_runcode ( RingState *pRingState,const char *cStr ) ;
List * ring_state_findvar ( RingState *pRingState,const char *cStr ) ;
List * ring_state_newvar ( RingState *pRingState,const char *cStr ) ;
void ring_state_main ( int argc, char *argv[] ) ;

739
Ring Documentation, Release 1.5.1

void ring_state_runfile ( RingState *pRingState,const char *cFileName ) ;


void ring_state_runobjectfile ( RingState *pRingState,const char *cFileName ) ;

69.3 Ring State Variables

We can create more than one ring state in the same program and we can create and modify variable values.
To get the variable list we can use the ring_state_findvar() function.
To create new variable we can use the ring_state_newvar() function.
Example:
#include "ring.h"
#include "stdlib.h"

int main(int argc, char *argv[])


{
List *pList;

RingState *pState = ring_state_init();


RingState *pState2 = ring_state_init();

printf("welcome\n");
ring_state_runcode(pState,"see 'hello world from the ring programming language'+nl");

printf("Again from C we will call ring code\n");


ring_state_runcode(pState,"for x = 1 to 10 see x + nl next");

ring_state_runcode(pState2,"for x = 1 to 5 see x + nl next");

printf("Now we will display the x variable value from ring code\n");


ring_state_runcode(pState,"see 'x value : ' + x + nl ");
ring_state_runcode(pState2,"see 'x value : ' + x + nl ");

pList = ring_state_findvar(pState,"x");

printf("Printing Ring variable value from C , %.0f\n",


ring_list_getdouble(pList,RING_VAR_VALUE));

printf("now we will set the ring variable value from C\n");


ring_list_setdouble(pList,RING_VAR_VALUE,20);

ring_state_runcode(pState,"see 'x value after update : ' + x + nl ");

pList = ring_state_newvar(pState,"v1");
ring_list_setdouble(pList,RING_VAR_VALUE,10);

pList = ring_state_newvar(pState,"v2");
ring_list_setdouble(pList,RING_VAR_VALUE,20);

ring_state_runcode(pState,"see 'v1 + v2 = ' see v1+v2 see nl");

ring_state_runcode(pState,"see 'end of test' + nl");

ring_state_delete(pState);

69.3. Ring State Variables 740


Ring Documentation, Release 1.5.1

ring_state_delete(pState2);
}

Output:
welcome
hello world from the ring programming language
Again from C we will call ring code
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
Now we will display the x variable value from ring code
x value : 11
x value : 6
Printing Ring variable value from C , 11
now we will set the ring variable value from C
x value after update : 20
v1 + v2 = 30
end of test

69.3. Ring State Variables 741


CHAPTER

SEVENTY

CODE GENERATOR FOR WRAPPING C/C++ LIBRARIES

In this chapter we will learn how to use the code generator to wrap C/C++ Libraries to use it in our Ring applications.

70.1 Using the tool

The code generator program is parsec.ring that can be executed as any ring code using the ring language.
URL : https://github.com/ring-lang/ring/tree/master/extensions/codegen
for example to read a configuration file called test.cf to generate the source code file test.c run parsec.ring as in the
next command
ring parsec.ring test.cf test.c

70.2 Configuration file

The configuration file (*.cf) is the input file that we pass to the code generator. This file determine the functions
prototypes that we need to use from a C/C++ library.
Writing configuration files is simple according to the next rules

70.3 Using the function prototype

To generate code that wraps a C function, we just write the C function prototype
Example:
ALLEGRO_DISPLAY *al_create_display(int w, int h)
void al_destroy_display(ALLEGRO_DISPLAY *display)
int al_get_new_display_flags(void)
void al_set_new_display_flags(int flags)
int al_get_new_display_option(int option, int *importance)

The previous example will guide the code generator to generate 5 functions that wraps the al_create_display(),
al_destroy_display(), al_get_new_display_flags(), al_set_new_diplay_flas() and al_get_new_display_option() func-
tions.
The generated code will be as in the next example

742
Ring Documentation, Release 1.5.1

RING_FUNC(ring_al_create_display)
{
if ( RING_API_PARACOUNT != 2 ) {
RING_API_ERROR(RING_API_MISS2PARA);
return ;
}
if ( ! RING_API_ISNUMBER(1) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
if ( ! RING_API_ISNUMBER(2) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
RING_API_RETCPOINTER(al_create_display( (int ) RING_API_GETNUMBER(1),
(int ) RING_API_GETNUMBER(2)),"ALLEGRO_DISPLAY");
}

RING_FUNC(ring_al_destroy_display)
{
if ( RING_API_PARACOUNT != 1 ) {
RING_API_ERROR(RING_API_MISS1PARA);
return ;
}
if ( ! RING_API_ISPOINTER(1) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
al_destroy_display((ALLEGRO_DISPLAY *) RING_API_GETCPOINTER(1,"ALLEGRO_DISPLAY"));
}

RING_FUNC(ring_al_get_new_display_flags)
{
if ( RING_API_PARACOUNT != 0 ) {
RING_API_ERROR(RING_API_BADPARACOUNT);
return ;
}
RING_API_RETNUMBER(al_get_new_display_flags());
}

RING_FUNC(ring_al_set_new_display_flags)
{
if ( RING_API_PARACOUNT != 1 ) {
RING_API_ERROR(RING_API_MISS1PARA);
return ;
}
if ( ! RING_API_ISNUMBER(1) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
al_set_new_display_flags( (int ) RING_API_GETNUMBER(1));
}

RING_FUNC(ring_al_get_new_display_option)

70.3. Using the function prototype 743


Ring Documentation, Release 1.5.1

{
if ( RING_API_PARACOUNT != 2 ) {
RING_API_ERROR(RING_API_MISS2PARA);
return ;
}
if ( ! RING_API_ISNUMBER(1) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
if ( ! RING_API_ISSTRING(2) ) {
RING_API_ERROR(RING_API_BADPARATYPE);
return ;
}
RING_API_RETNUMBER(al_get_new_display_option( (int ) RING_API_GETNUMBER(1),
RING_API_GETINTPOINTER(2)));
RING_API_ACCEPTINTVALUE(2) ;
}

from the previous example we can see how much of time and effort is saved using the Code Generator.

70.4 Adding code to the generated code

To generate code directly type it between <code> and </code>


Example :
<code>
/* some C code will be written here */
</code>

We use this feature when we need to do something without the help of the code generator. for example including
header files and defining constants using Macro.

70.5 Prefix for Functions Names

To determine a prefix in all of the functions names type it between <funcstart> and </funcstart> for ex-
ample when we wrap the Allegro game programming library and we need all of the library functions
to start with al we type the next code in the configuration file
<funcstart>
al
</funcstart>

70.6 Generate function to wrap structures

To generate functions that wrap structures (create/delete/get structure members)


just type the structures names between <struct> and </struct> also after the structure name you can type the structure
members between { } separated by comma.
Example

70.4. Adding code to the generated code 744

You might also like