4.6.1 Passing Arguments to OC

Summary

When working between LabTalk and Origin C, you may need to pass variables in your code. In LabTalk, numeric variables (int, double, etc.), string variables and column level range variables can be passed directly. Other LabTalk objects (like worksheet range, graph page range, etc.) should be passed by strings, and then work with these strings within Origin C functions. The following table summaries how to deal with function arguments when passing value from LabTalk to Origin C:

LabTalk Data Type Origin C Argument Support passing reference
double double Yes
int int Yes
string string Yes
column level range DataRange No
range string No
string registers string No
loose dataset vector No
string array vector<string> No
tree Tree Yes

Please look into the following examples to see how to deal with different cases:

Examples

Pass int by value

This example is designed to show the trace interoplation, which acts on the curve based on X index number, thus preserving the sequential aspect of the data. The example is completed by a combination of Origin C and LabTalk. integral n, which stands for the order of the curve, is passed to Origin C by LabTalk.

Tract int.png

Origin C code:

#include <origin.h>
#define aa 0.5
void main_Data(int n)
{
    vector<double> x={0}, y={0};
    hilbert_2D(n, x, y);
    Worksheet wks=Project.ActiveLayer(); 
    if (wks){   		
        Dataset c1(wks,0);
        Dataset c2(wks,1);        
        c1=x;
	c2=y;
    }    
}

void hilbert_2D(int n, vector<double> &x, vector<double> &y)  //create the hilbert curve
{	
	vector x0 = {0}, y0 = {0};	
	while(n-->0){
		x0=x; y0=y;
		x.RemoveAll();
		y.RemoveAll();	
		x.Append(aa*(-aa+y0));	
		x.Append(aa*(-aa+x0));
		x.Append(aa*(aa+x0));
		x.Append(aa*(aa-y0));

		y.Append(aa*(-aa+x0)); 
		y.Append(aa*(aa+y0));
		y.Append(aa*(aa+y0));
		y.Append(aa*(-aa-x0));	
	}
}

LabTalk script:

newbook name:="Trace_Interp";
main_Data(4);  // the 4-th order Hilbert curve  
interp1trace -r 2 iy:=[Trace_Interp]1!(A,B) method:=spline;  //perform trace interpolate on curve using spline method.
plotxy iy:=((1,2),(3,4)) plot:=200;
set %C -w 1500; // Set line width

Pass double by value

You can pass a double, int or string variable directly into Origin C function.

Origin C code:

#include <origin.h>

double GetLarger(double a, double b)
{
    return a>b?a:b;
}

LabTalk script:

double a = 3.5, b = 8.9;
double c = GetLarger(a, b);
ty "The larger value is $(c)";

Pass integer by reference

Data type like double, int and string can also be passed by reference:

Origin C code:

#include <origin.h>

void MySwap(int& a, int& b)
{
    int temp;
    if(a<b)
    {
        temp = a;
        a = b;
        b = temp;
    }
}

LabTalk script:

int a = 10, b = 20;
ty "First, a = $(a), and b = $(b)";
MySwap(a, b);
ty "Then, a = $(a), and b = $(b)";

Pass string by reference

String variable can be passed directly into Origin C function, and can also be passed by reference:

Origin C code:

#include <origin.h>

int CheckFile(string& strFile, string& strExt)
{
    int nRet = strFile.IsFile();
    if(nRet != 0)
    {
    	separate_file_name_ext(strFile, NULL, &strExt);
    	strFile = GetFileName(strFile, TRUE);
    }
    
    return nRet;
}

LabTalk script:

string strFile$ = %Y;
strFile$ =strFile$+"origin.ini";
string strExt;
CheckFile(strFile$, strExt$);
ty "strFile=%(strFile$), strExt=%(strExt$)"

Pass string array

You can use vector to make a copy of string array or loose dataset inside Origin C.

Origin C code:

#include <origin.h>
 
void TyMyLove(vector<string> strA)
{
    int nSize = strA.GetSize();
    for(int i=0; i<nSize; i++)
    {
        printf("I Love %s!\n", strA[i]);
    }
}

LabTalk script:

stringarray aa;
aa.Add("Boston");
aa.Add("New York");
aa.Add("Los Angeles");
TyMyLove(aa);

Pass column range

column range variable can be passed directly.

The following example shows how to pass a column range into Origin C:

Minimum Origin Version Required: 9.0 SR1

Origin C code:

#include <origin.h>

double MyMean(DataRange dr)
{
	double dMean;
        int nN;	
	vector vec;
	dr.GetData(&vec, 0);
	int nRet = ocmath_basic_summary_stats(vec.GetSize(), vec, &nN, &dMean);
	if(0 == nRet)
		return dMean;
        return NANUM;
}

LabTalk script:

newbook;
col(1) = data(0, 100);
range rr = [%H]1!1;
double Rmean=MyMean(rr);
ty "The Mean of %(rr) is $(Rmean)";
Note:
  1. The range can refer to one column as well as a range of column(s). For example, range [book1]sheet1!1[2]:2[5] can be resolved inside Origin C function directly.
  2. Before Version 9 Service Release 1, when working with range, you need to pass the range name as string into Origin C functions. See the section below to see how to pass range as string.

Pass worksheet range

When passing with worksheet range, you can pass the worksheet range name, using %() notation or pass a string variable, as string into Origin C functions. Inside the Origin C function, you can resolve the string into proper object by okxf_resolve_string_get_origin_object() function (should include xfutils.h), or you can also create a proper object from the string.

Do remember to quote the range name in the LabTalk script, or use a string variable directly, to pass a string explicitly.

Origin C code:

#include <Origin.h>
#include <xfutils.h>

int MyCopyWks(string strSource, string strTarget)
{
    Worksheet sWks, tWks;
    int nRet = okxf_resolve_string_get_origin_object(strSource, &sWks);
    nRet *= okxf_resolve_string_get_origin_object(strTarget, &tWks);
    if( !nRet )
    {
        printf("Worksheet name is wrong!\n");
        return 0;
    }
    sWks.CopyTo(tWks, 0, -1, 0, -1, 0);
    return 1;
}

LabTalk script:

range ra = [book1]sheet1!;
range rb = [book2]sheet1!;
int nRet = MyCopyWks("%(ra)", "%(rb)");

Pass data plot range

Similar to working with worksheet range, you can also pass a plot range as string into Origin C.

When communicating between LabTalk and Origin C, be aware that the starting index are different.

Origin C code:

#include <Origin.h>
#include <xfutils.h>

int ChangeDPColor(string strDP, int nColor)
{
    DataPlot dp;
    int nRet = okxf_resolve_string_get_origin_object(strDP, &dp);
    if( !nRet )
    {
        printf("Not a valid data plot!\n");
        return 0;
    }
    if( nColor < 1 || nColor > 24 )
    {
        printf("LabTalk color number sould be 1 ~ 24!\n");
    }
    // Color index in Origin C starts from 0
    nColor--;
    dp.SetColor(nColor, TRUE);
    return 1;
}

LabTalk script:

newbook;
col(1) = data(1, 10);
col(2) = col(1);
white_noise 2;
plotxy 2 202;
Range dp = [%H]1!1;
string strDP$ = %(dp);
int nC = color(green);
int nRet = ChangeDPColor(strDP$, nC);

Pass window name

You can pass the window name directly into Origin C function. If there are proper object constructor, you can then create the corresponding object in Origin C.

Origin C code:

#include <Origin.h>

int GetPlotsNum(string pName)
{
    int nPlots = 0;
    GraphPage gp(pName);
    if( !gp.IsValid() )
    {
        printf("Not a valid page!\n");
        return 0;
    }
    foreach( GraphLayer gl in gp.Layers )
    {
        foreach( DataPlot dp in gl.DataPlots )
            nPlots++;
    }
    
    return nPlots;
}

LabTalk script:

newbook;
string fname$ = system.path.program$;
fname$ += "Samples\Curve Fitting\Exponential Decay.dat"; 
impasc;
worksheet -s 0 0 -1 -1;
worksheet -p 201;
int nPlots = GetPlotsNum("%H");
ty "There are $(nPlots) plots in %H";

Pass tree

You can pass the tree directly into Origin C function.

Origin C code:

#pragma labtalk(4)
int tt(Tree& tr, string strAppsPath)
{
	Tree tr1;
	if(!tr1.Load(strAppsPath))
		return 1;
	tr.Replace(tr1, TRUE, TRUE);
	return 0;
}
#pragma labtalk(0)

LabTalk script:

Tree tr1;
string strApps$="%@AOpxList.xml";
if(0==tt(tr1,strApps$))
	tr1.=;

Construct LabTalk Tree with XML

You can construct LabTalk tree with XML

Origin C code for XML:

string st(string strAppsPath)
{
	string str;
	Tree tr;
	if(tr.Load(strAppsPath)) {
		tr.GetString(str);
		return str;
	}
}

LabTalk script:

string strApps$="%@AOpxList.xml";
string strXML$ = st(strApps$)$;
Tree tr1 = strXML$;
tr1.=

This can be used for Data Connector. For example, after import a CSV file, run the following scripts to get the import dialog settings.

Tree tr1=wks.dc.optn$;
tr1.=;

And the reverse is also supported:

string str$ = wks.dc.optn$;
Tree tr1 = str$;
tr1.=;

Return range by string

Most Origin C objects cannot return to LabTalk either. So, if you want to return a range, you can use the GetRangeString() method to return the range string back to LabTalk.

Origin C code:

#include <origin.h>
#include <xfutils.h>

// This function insert 3D scatter to layer strGL using data from strWksName
int Insert3DScatter(string strGL, string strWksName)
{
    // Get graph layer object by name
    GraphLayer gl;
    if( !okxf_resolve_string_get_origin_object(strGL, &gl) )
    {
        out_str("Invalid graph layer!");
        return 0;
    }
    // Construct worksheet by name
    Worksheet wks(strWksName);
 
    DataRange dr;
    int nR = 0;
    dr.Add("X", wks, 0, 0, -1, 0);
    dr.Add("Y", wks, 0, 1, -1, 1);
    nR = dr.Add("Z", wks, 0, 2, -1, 2);
    // Add a 3D scatter plot
    int nPlot = gl.AddPlot(dr, ID_3D_GRAPH_SCATTER);
    if( nPlot == -1 )
    {
        out_str("Cannot add plot!");
        return 0;
    }
    DataPlot dp = gl.DataPlots(nPlot);
    Tree tr;
    tr = dp.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE);
    tr.Root.Symbol.Shape.nVal = 11;
    tr.Root.Symbol.Interior.nVal = 8;
    tr.Root.Symbol.EdgeColor.nVal = 15;
    tr.Root.DropLines.Z.nVal = 0;
    if( !dp.ApplyFormat(tr, TRUE, TRUE) )
    {
        out_str("Apply format failed!");
        return 0
    }
    return 1;
}

// This function create a transparent mesh graph
// The graph layer name, strGLName, is passed by reference, 
// we can then reuse this variable in LabTalk
int CreateMeshPlot(string strMOName, string& strGLName)
{
    // Get matrix object by name
    MatrixObject mo(strMOName);
    okxf_resolve_string_get_origin_object(strMOName, &mo);
    GraphPage gp;
    gp.Create("mesh");
    GraphLayer gl = gp.Layers();
    // Add mesh plot to layer
    int nPlot = gl.AddPlot(mo, IDM_PLOT_3D_MESH);
    if( nPlot < 0 )
    {
        out_str("Cannot create 3D mesh!");
        return 0;
    }
    // Fine tune the plot
    DataPlot dp = gl.DataPlots(nPlot);
    Tree tr;
    tr = dp.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE);
    tr.Root.Grids.FrontColor.nVal = 8;
    tr.Root.Grids.BackColor.nVal = 8;
    tr.Root.Grids.Width.dVal = 0.8;
    tr.Root.Grids.Color.dVal = 19;
    tr.Root.Grids.Transparency.nVal = 70;
    if( !dp.ApplyFormat(tr, TRUE, TRUE) )
    {
        out_str("Apply format failed!");
        return 0
    }
    // Return graph layer range string
    gl.GetRangeString(strGLName);
    gl.Rescale();
    return 1;
}

LabTalk script:

newbook;
string fname$ = system.path.program$;
fname$ += "Samples\Matrix Conversion and Gridding\XYZ Random Gaussian.dat"; 
impasc;
range rw = [%H]1!3;
rw.type = 6;
xyz_renka iz:=rw rows:=20 cols:=20;
range rm = [%H]1!1;
// Passing range as string, and pass string variable by reference
string strGLName$;
CreateMeshPlot("%(rm)", strGLName$);
// Pause two seconds
sec -p 3;
string strWksName$ = rw.GetLayer()$;
// Passing layer name, worksheet name as string
Insert3DScatter(strGLName$, strWksName$);