ObjectScript API, integration with C ++. Part 3: connecting a module with functions in C ++
- Tutorial
ObjectScript is a new open source object-oriented programming language. ObjectScript extends the capabilities of languages such as JavaScript, Lua, and PHP.
Let's create our module with functions that will be available in OS code. We call the module
To begin with, you need to write the functions of our future module in C ++, the first one
A little explanation on the bill:
Here we get the first parameter as a string.
The C ++ API provides a number of functions for getting various simple types from the stack:
Sometimes a lot of work with the stack happens in a C ++ program. In this case, in order not to keep relative offsets in mind (since they will change when something is added or removed from the stack), it’s convenient to work with an absolute pointer to a value in the stack, you can get it with a function
This was a digression, now the second function of our module is
A small explanation on the bill:
This is the number of values returned by the function. The functions are ready, now we need to inform the OS that we have a new module with the following functions:
Now let's check how it works, write a program on OS (main.os), which for each value of the test array will call our functions in C ++:
The program will output the following result:
Full source code in C ++:
You can download the ObjectScript source code and an example from this article at this link , open proj.win32 \ examples.sln , the add_user_module project .
Other relevant articles about ObjectScript:
PS A small opus about
OS :: String is an object with an ObjectScript string that can be stored in custom C ++ code. Such a string retains a valid value all the time of its existence. To get to point to a null-terminated string, you need to use a function
Q: What will happen if you execute
A:OS :: String captures an OS instance, letting it know that it is used in external code. Therefore
Part 3: connecting a module with functions in C ++
Let's create our module with functions that will be available in OS code. We call the module
my
, it will contain two functions:isdigit
will check if the string passed in the parameter consists of numbers onlyhash
will convert the parameter to a hash string according to our algorithm
To begin with, you need to write the functions of our future module in C ++, the first one
my_isdigit
:static int my_isdigit(OS * os, int params, int, int, void*)
{
OS::String str = os->toString(-params);
int len = str.getLen();
for(int i = 0; i < len; i++){
if(!isdigit(str[i])){
os->pushBool(false);
return 1;
}
}
os->pushBool(len > 0);
return 1;
}
A little explanation on the bill:
OS::String str = os->toString(-params);
Here we get the first parameter as a string.
params
- this is the number of parameters that were passed to the function from the OS. -params
Is the relative pointer in the stack to the first parameter. If we needed to turn to the second parameter, then it would look like this:, os->toString(-params+1)
to the third - os->toString(-params+2)
and so on. The C ++ API provides a number of functions for getting various simple types from the stack:
toFloat, toDouble, toInt, toString, toUserdata, popFloat
etc. Sometimes a lot of work with the stack happens in a C ++ program. In this case, in order not to keep relative offsets in mind (since they will change when something is added or removed from the stack), it’s convenient to work with an absolute pointer to a value in the stack, you can get it with a function
getAbsoluteOffs(int offs)
and work like this :int params_offs = os->getAbsoluteOffs(-params);
OS::String str = os->toString(params_offs); // перпый параметр
OS::String str = os->toString(params_offs+1); // второй
This was a digression, now the second function of our module is
my_hash
:static int my_hash(OS * os, int params, int, int, void*)
{
OS::String str = os->toString(-params);
int i, len = str.getLen(), hash = 5381;
for(i = 0; i < len; i++){
hash = ((hash << 5) + hash) + str[i];
}
hash &= 0x7fffffff;
char buf[16];
for(i = 0; hash > 0; hash >>= 4){
buf[i++] = "0123456789abcdef"[hash & 0xf];
}
buf[i] = 0;
os->pushString(buf);
return 1;
}
A small explanation on the bill:
return 1;
This is the number of values returned by the function. The functions are ready, now we need to inform the OS that we have a new module with the following functions:
void initMyModule(OS * os)
{
OS::FuncDef funcs[] = {
{"isdigit", my_isdigit},
{"hash", my_hash},
{}
};
os->getModule("my");
os->setFuncs(funcs);
os->pop();
}
Now let's check how it works, write a program on OS (main.os), which for each value of the test array will call our functions in C ++:
for(var i, s in ["123", "12w", 1234, " df", " "]){
print("my.isdigit("..s..") = "my.isdigit(s)" my.hash("..s..") = "my.hash(s))
}
The program will output the following result:
my.isdigit(123) = true my.hash(123) = bf9878b
my.isdigit(12w) = false my.hash(12w) = f3a878b
my.isdigit(1234) = true my.hash(1234) = f89c87c7
my.isdigit( df) = false my.hash( df) = f48478b
my.isdigit( ) = false my.hash( ) = 5082f6c7
Full source code in C ++:
#include "objectscript.h"
#include
using namespace ObjectScript;
static int my_isdigit(OS * os, int params, int, int, void*)
{
OS::String str = os->toString(-params);
int len = str.getLen();
for(int i = 0; i < len; i++){
if(!isdigit(str[i])){
os->pushBool(false);
return 1;
}
}
os->pushBool(len > 0);
return 1;
}
static int my_hash(OS * os, int params, int, int, void*)
{
OS::String str = os->toString(-params);
int i, len = str.getLen(), hash = 5381;
for(i = 0; i < len; i++){
hash = ((hash << 5) + hash) + str[i];
}
char buf[16];
hash &= 0x7fffffff;
for(i = 0; hash > 0; hash >>= 4){
buf[i++] = "0123456789abcdef"[hash & 0xf];
}
buf[i] = 0;
os->pushString(buf);
return 1;
}
void initMyModule(OS * os)
{
OS::FuncDef funcs[] = {
{"isdigit", my_isdigit},
{"hash", my_hash},
{}
};
os->getModule("my");
os->setFuncs(funcs);
os->pop();
}
void main()
{
OS * os = OS::create();
initMyModule(os);
os->require("main.os");
os->release();
}
You can download the ObjectScript source code and an example from this article at this link , open proj.win32 \ examples.sln , the add_user_module project .
Other relevant articles about ObjectScript:
- ObjectScript API, integration with C ++. Part 2: running a script on OS from C ++
- ObjectScript API, integration with C ++. Part 1: working with the stack, calling OS functions from C ++
- ObjectScript - a new programming language
PS A small opus about OS::String
OS :: String is an object with an ObjectScript string that can be stored in custom C ++ code. Such a string retains a valid value all the time of its existence. To get to point to a null-terminated string, you need to use a function
toChar()
. ObjectScript stores in memory all different lines in a single copy , therefore it OS::String
is a constant line, it cannot be changed under any circumstances. But you can get a new line. OS::String
implements a number of designers and the concatenation operator, so it OS::String
is quite possible to create from user code and work with it (if necessary). Q: What will happen if you execute
os->release()
before the lines OS::String
stored in the user code are destroyed ? A:OS :: String captures an OS instance, letting it know that it is used in external code. Therefore
os->release()
, it will not destroy an OS instance, but it will be destroyed when the last line OS::String
ceases to exist.