Difference between revisions of "MC-Basic C-Interface"

From SoftMC-Wiki
Jump to: navigation, search
m
m
Line 1: Line 1:
The softMC offers users an outstanding option to incorporate applications written in C or C++ into an MC-Basic task.You can write your algorithm in C/C++, compile it with a GNU compiler, download it into a target program and call the code from a program written in MC-Basic or directly from the command line.
+
== Introduction ==
 +
The softMC offers users an option to incorporate applications written in C or C++ into an MC-Basic task. You can write your algorithm in C/C++, compile it with a GNU compiler, download it into a target program and call the code from a program written in MC-Basic or directly from the command line.
  
 
The parameters can be passed by value as well as by reference. This function returns a value that can be processed by an MC-Basic application.
 
The parameters can be passed by value as well as by reference. This function returns a value that can be processed by an MC-Basic application.

Revision as of 12:23, 2 April 2014

Introduction

The softMC offers users an option to incorporate applications written in C or C++ into an MC-Basic task. You can write your algorithm in C/C++, compile it with a GNU compiler, download it into a target program and call the code from a program written in MC-Basic or directly from the command line.

The parameters can be passed by value as well as by reference. This function returns a value that can be processed by an MC-Basic application.

MC-Basic provides a facility to load a user object-file into the RAM of the softMC. This file is relocatable and must include information about global symbols for the softMC to find the C-function. The object module may consist of any number of functions. The only restriction is RAM limit.

Object Files

Object files (extension “.o”), contain compiled C-programs and are stored in the Flash disk. You can SEND object files to the controller, load files into RAM with OLOAD and unload them with OUNLOAD. If OLOAD/OUNLOAD fails for any reason, details are found in the OLOAD.ERR file.

Prototype File

For the MC-Basic language translator to match function parameters, provide a C-function prototype file (PROTO.PRO). It is important to understand that matching between the provided softMC prototype and actual C implementation cannot be tested by the translator. It is your responsibility to keep consistency between the function prototype and C implementation.


NOTE-Info.svgNOTE
To speedup translation of the prototype file, PROTO.PRO is copied into RAM at startup and at every OLOAD. When PROTO.PRO is modified and sent to the controller, issue an OLOAD or reboot the softMC to refresh the prototypes in the RAM.

The translator is case-insensitive, while object module loader is case-sensitive, so write the name of a C function in capital letters within the C code. softMC prototypes of C functions and C function calls through the softMC are not case sensitive.

Parameters can be passed “by value” and “by reference”

Few object files may be incrementally linked together.

The general syntax for the softMC prototype of a C-function is:

IMPORT_C <Function_Name> ({AS <type>}, {BYVAL AS {<type>}) {AS <type>}

A parameter passed by value has the BYVAL prefix.

A parameter passed by reference has no prefix.

Prototypes do not include parameter names.

A C function prototype with no parameters is written with empty parentheses:

IMPORT_C <Function_Name> ( ) {AS <type>}

A C function prototype with no returned value (a void function) is written as:

IMPORT_C <Function_Name> ({AS <type>}, {BYVAL AS {<type>})

A C-function accepts any combination of double-, long- and string-type parameters. The parameters may be passed “by value” or “by reference”.

The returned value may be long, double, string or none (for C functions with void returned value).

Examples of prototypes and implementation:


MC-Basic Prototype
C Implementation
import_c cFunc_LV As Long int CFUNC_LV(void);
import_c cFunc_DV As double double CFUNC_LV(void);
import_c cFunc_SV As string char* CFUNC_LV(void);
import_c cFunc_VV() void CFUNC_VV(void);
import_c cFunc_LL(ByVal As Long) As Long int CFUNC_LL(int L);
import_c cFunc_DRD(As Double) As Double double CFUNC_DRD(double* D);
import_c cFunc_SRS(As String) As String char* CFUNC_SRS(char** S);
Import_C cFunc_LARD([*] as Long) as Double double CFUNC_LARD(long *l);
import_c cFunc_SS(ByVal As String) As String char* CFUNC_SS(char* S);

Parameters can be of type long, double or string; in any order, up to 32 parameters.

Only one-dimensional arrays are allowed as C-functions arguments.

Example of calling a C-function from MC-Basic:

Dim shared Str2global as string

Dim shared Str1global as string

Dim shared LongArray[100] as long

Dim shared d1 as double

program

' Use OLOAD to load the object file before loading the program

' that uses the C-Functions


' /* No Parameters */ 

' int CFUNC_LV(void) 

?CFUNC_LV()


' double CFUNC_DV(double) 

?CFUNC_DRD(1.2345)


' /* returns string */

char* CFUNC_SV(void)

?CFUNC_SV()


' /* No Parameters, not return value */

' void CFUNC_VV(void)

CFUNC_VV()

' /* Strings */

' char* CFUNC_SS(char* S)

Str2global=CFUNC_SS(Str1global)


' /* Arrays */

' double CFUNC_LARD(long *l);

d1= cFunc_LARD(LongArray)

end program

Example of PROTO.PRO:

'No Parametrs

import_c CFUNC_LV() As Long

import_c CFUNC_DV() As Double

import_c CFUNC_SV() As String

import_c CFUNC_VV()

'A Single "By Value" Parameter

import_c CFUNC_LL(ByVal As Long) As Long

import_c CFUNC_DD(ByVal As Double) As Double

import_c CFUNC_SS(ByVal As String) As String

'A Single "By Reference" Parameter

import_c CFUNC_LRL(As Long) As Long

import_c CFUNC_DRD(As Double) As Double

import_c CFUNC_SRS(As String) As String

'Multiple "By Value" Parametrs

import_c CFUNC_LVALP(ByVal As double, ByVal As Long, ByVal As String) As Long

import_c CFUNC_VVALP(ByVal As String, ByVal As double, ByVal AS Long)

'Multiple "By Reference" Parameters

import_c CFUNC_DREFP(As String, As Long, As Double) As Double

import_c CFUNC_VREFP(As Long, As Double, As String)

' Mixed Parameters

import_c CFUNC_VMIXP(ByVal As Long,As Double,ByVal As String,As String,As Long,ByVal As double) AS Long

Example of test.c:

/* No Parameters */

int CFUNC_LV(void)

{

return 1;

}

double CFUNC_DV(void)

{

return 2.2;

}

char* CFUNC_SV(void)

{

return "SV";

}

void CFUNC_VV(void)

{

int fd = open("/tyCo/1",2,0);

fdprintf(fd,"VV\r\n");

close(fd);

}

/* A Single "By Value" Parameter */

int CFUNC_LL(int L)

{

L = L + 1;

return L;

}

double CFUNC_DD(double D)

{

D = D + 2.2;

return D;

}

char* CFUNC_SS(char* S)

{

strcpy(S,"SS");

return S;

}

/* A Single "By Reference" Parameter */

int CFUNC_LRL(int* L)

{

*L = *L + 3;

return *L;

}

double CFUNC_DRD(double* D)

{

*D = *D + 4.4;

return *D;

}

char* CFUNC_SRS(char** S)

{

strcpy(*S,"SRS");

return *S;

}

/* Multiple Parameters */

/* By Value Parameters */

int CFUNC_LVALP(double D, int L, char* S)

return (D + L + atoi(S)); 

} 

void CFUNC_VVALP(char* S, double D, int L)

{

int fd = open("/tyCo/1",2,0);


fdprintf(fd,"Original Values:%d, %f, %s\r\n", L, D, S);


L = 10;

D = 22.2;

strcpy(S,"VValP");


fdprintf(fd,"New Value:%d, %f, %s\r\n", L, D, S);


close(fd); 

} 


/* By Reference Parameters */

double CFUNC_DREFP(char** S, int* L, double* D)

{

return (*D + *L + atof(*S)); 

}

Special Considerations

Motion and System properties can only be passed by value.

KILLTASK will not unblock a task locked inside the C-function. An endless block on a semaphore, message queue, etc. inside a C-function prevent sa task from correct being killed. If C-function has some blocking operation system call (taskDelay(), semTake(), msgQGet(), msqQSend(), IO operation, etc.), this may interfere with killing the user task.

When an object module is loaded several times without unloading, all its instances are kept in the RAM, while the system symbol table has references only to the resent instance. MC-Basic applications may refer to the obsolete version of some modified object file.

OUNLOAD does not check to see if the object file is in use. It is your responsibility to ensure that the object is not unloaded as long as there tasks and libraries that refer to the object.

Consider following example, both the program TASK1.PRG and TASK2.PRG use the same function from object module.

-->oload my_obj.o

-->load TASK1.PRG

-->send my_obj.o ‘ send updated version of object file

-->oload my_obj.o

-->load TASK2.PRG

In this example, TASK1.PRG references the oldest instance of my_obj.o while TASK2.PRG references the recent version.