Program Examples:Shared Objects/zh-hans

From SoftMC-Wiki
Jump to: navigation, search
语言: English  • 中文(简体)‎

以下示例演示如何在Linux中编译共享对象并在运行时将其与softMC进行链接。

下面有5个示例文件:C源文件,C头文件,CPP源文件,CPP头文件和makefile。
源文件和头文件实现一个简单的程序,给出2个整数作为参数,并返回其总和或差。
该程序不包括主函数,因此程序只能编译为库,而不是可执行程序。


示例程序

C 源文件: Example.c

#include <stdio.h>

#include "Example.h"

/**************************    Linux sys.log Declarations    ******************************/

/* MC Modules */
#define MODULE_NON	 	 0
#define MODULE_MOTION		 1
#define MODULE_RTS		 2
#define MODULE_TRANSLAT		 3
#define MODULE_SERCOS		 4
#define MODULE_ROBOT		 5
#define MODULE_TRACER		 6
#define MODULE_SYSTEM		 7
#define MODULE_MEMORY		 8
#define MODULE_FILE_SYSTEM	 9
#define MODULE_CLI		10
#define MODULE_RBOOTP		11
#define MODULE_ETHERCAT		12
#define MODULE_FASTDATA		13
#define MODULE_UAC		14
#define MODULE_MC_BASIC		15
#define MODULE_CANOPEN		16


/* MC Log Level */
#define LOG_LEVEL_NON		0
#define LOG_LEVEL_ERROR		1
#define LOG_LEVEL_WARNING	2
#define LOG_LEVEL_NOTE		3
#define LOG_LEVEL_DEBUG		4
#define LOG_LEVEL_ALL		5

extern int sys_log(int sub_system, int _debug_level, const char * fmt, int arg1, int arg2,
			int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10);

/******************************************************************************************/



int SHARED_OBJECT_SUM(int arg1, int arg2)
{
	sys_log(MODULE_NON, LOG_LEVEL_ERROR, "%s: arg1 = %d, arg2 = %d\n", (int)__FUNCTION__, arg1, arg2, 0,0,0,0,0,0,0);
	print_hello();

	return arg1 + arg2;
}

void print_hello(void)
{
	fprintf(stderr, "Hello! This is just an example\n");
}
/*
 * This function is called when module is unloaded:
 * 1) at "ounload"
 * 2) at "reset all"
 */
__attribute__ ((__destructor__))
void exit_func(void) 
{
/*
 * Make cleanup here, kill threads, release resources, etc.
 */
}

C 头文件: Example.h

void print_hello(void);

CPP 源文件: CPP_Example.c

#include <iostream>

#include "CPP_Example.h"

extern "C" {

int SHARED_OBJECT_SUB(int arg1, int arg2)
{
	print_hello_cpp();

	return arg1 - arg2;
}

} // extern "C" {

void print_hello_cpp(void)
{
	std::cerr << "A cpp example" << std::endl;
}
/*
 * This function is called when module is unloaded:
 * 1) at "ounload"
 * 2) at "reset all"
 */
__attribute__ ((__destructor__))
void exit_func(void) 
{
/*
 * Make cleanup here, kill threads, release resources, etc.
 */
}

CPP头文件: CPP_Example.h

void print_hello_cpp(void);
IMPORTANT.svgIMPORTANT
在声明将从MC-Basic上下文中使用的函数名时,必须使用大写字母,如SHARED_OBJECT_SUM和SHARED_OBJECT_SUB的示例中所示。
用户函数必须用extern“C”封装,以避免CPP破坏名称


printf和fprintf等函数的输出字符串通常显示在Linux终端中,但在softMC的情况下,行为是不同的。
printf和cout的输出被丢弃,而fprintf和cerr的输出字符串被引导到被称为“nohup”的对象,并且稍后可被用户读取。
要显示nohup的内容,请执行以下操作:

1. 使用ssh或串口控制台连接到softMC。
2. 在Linux终端中:

-bash-3.2$ cat /var/home/mc/nohup.out
....
....
Hello! This is just an example
A cpp example

获取编译器

使用编译器和链接器来构建共享对象,由makefile中的CC变量定义。
您需要任何linux安装(如Ubuntu)才能运行softMC编译器。

剪切并粘贴以下命令到Linux命令行::
cd ~
wget --no-check-certificate http://servotronix.com/html/softMC_Tool_Chain/0B-jc7OYLo3AYaGFfN2ZkTUNJdHM.tar
tar -zxvf 0B-jc7OYLo3AYaGFfN2ZkTUNJdHM.tar

完整的softMC工具链将安装到您的主目录中 ~/OSELAS.Toolchain-2011.03.1

如果您正在使用64位Linux,请安装以下软件包:

sudo apt-get install libc6-i386
sudo apt-get install zlib1g:i386

Makefile

请注意,makefle CC变量分配有一个完整的gcc编译器路径。 这个特定的gcc是我们用来构建softMC的工具链的一部分。 编译要与softMC链接的共享对象时,建议使用OSELAS.Toolchain-2011.03.1工具链。
示例中的CFLAGS和CPPFLAGS变量可能会导致编译错误。但您可以删除那些妨碍编译成功的内容,但不建议这样做。更好的选择是修复编译错误

The makefile syntax:

CC=~/OSELAS.Toolchain-2011.03.1/i586-unknown-linux-gnu/gcc-4.5.2-glibc-2.13-binutils-2.21-kernel-2.6.36-sanitized/bin/i586-unknown-linux-gnu-gcc
CXX=~/OSELAS.Toolchain-2011.03.1/i586-unknown-linux-gnu/gcc-4.5.2-glibc-2.13-binutils-2.21-kernel-2.6.36-sanitized/bin/i586-unknown-linux-gnu-g++
CFLAGS=-c -g -ansi -pedantic -Wall -Werror
CPPFLAGS=-c -g -ansi -pedantic -Wall -Werror

LD_LIBRARY_PATH := .:$(LD_LIBRARY_PATH)

C_SOURCE=Example.c
CPP_SOURCE=CPP_Example.cpp

C_OBJECTS=$(C_SOURCE:.c=.o)
CPP_OBJECTS=$(CPP_SOURCE:.cpp=.o)

TARGET=EXAMPLE.O

$(TARGET): $(C_OBJECTS) $(CPP_OBJECTS)
	$(CC) -shared -o $@ $(C_OBJECTS) $(CPP_OBJECTS)

$(C_OBJECTS): $(C_SOURCE)
	$(CC) $(CFLAGS) -c $(C_SOURCE)

$(CPP_OBJECTS): $(CPP_SOURCE)
	$(CXX) $(CPPFLAGS) -c $(CPP_SOURCE)

clean:
	rm $(C_OBJECTS) $(CPP_OBJECTS) $(TARGET)

为了使makefile适应您的需要,请将变量“C_SOURCE”和“CPP_SOURCE”的分配更改为项目中源文件的名称以及变量“TARGET”的赋值。

IMPORTANT.svgIMPORTANT
softMC只能处理限制为8.3约定的大写字母文件名,最多8个字符,后跟一个点,后跟扩展名PRG或LIB或O(当然在本例中为.O)
在分配TARGET变量时请记住

编译成功后,您将在工作目录中找到文件EXAMPLE.O,或者将任何字符串分配给变量“TARGET”。

将共享对象复制到softMC

您可以通过两种不同的方式将共享对象复制到softMC::
1. 使用scp,将文件直接复制到softMC。
在Linux终端类型中:

my_user@my_computer:~/working_directory$ scp EXAMPLE.O mc@mc.ip.add.ress:/FFS0/SSMC

其中mc.ip.add.ress是sfotMC的ip地址,例如 192.168.7.152.
or
2. 使用ControlStudio的文件管理器将文件EXAMPLE.O拖放到softMC。

将共享对象与softMC链接

共享对象现在位于softMC内。 现在我们要在运行时将softMC与共享对象链接起来,并使用它。 链接共享对象在CONFIG.PRG上下文中用'oload'命令完成。 将下行添加到您的CONFIG.PRG::

oload EXAMPLE.O

现在我们需要声明共享对象的内容以及如何使用它。 这是由PROTO.PRO文件完成的。 请将以下行添加到PROTO.PRO文件中:

import_c SHARED_OBJECT_SUM(byval as long, byval as long) as long
import_c SHARED_OBJECT_SUB(byval as long, byval as long) as long

当然,'SHARED_OBJECT_SUM'是在Example.c中实现的一个函数。 您将需要指定您自己的功能的原型。
使用ControlStudio将编辑好的CONFIG.PRG和PROTO.PRO发送到softMC并键入ControlStudio终端“reset all”。

如果进程成功,您现在可以从共享对象中调用函数。 在ControlStudio终端键入:

-->
-->
-->
-->?SHARED_OBJECT_SUM(5, 6)
11
-->
-->
-->?SHARED_OBJECT_SUB(5, 6)
-1
-->


将MC-Basic字符串传递给C函数

例如,可以将字符串对象发送到C函数进行解析。 为了做到这一点,你需要在代码中加入以下声明::

typedef int			INT32;
typedef unsigned int		UINT32;
typedef pthread_mutex_t*	SEMM_ID;
typedef int			FUNCPTR;	/* ptr to func returning int   */


/* defining MC Basic SYS String */
typedef struct {
	INT32 type;				/* string type */
	INT32 scope;				/* string variable scope */
	INT32 temp;				/* memory release flag */
	INT32 alloc_size;			/* number of bytes allocated */
	INT32 occup_size;			/* number of bytes occupied */
	INT32 num_chars;			/* number of characters */
	UINT32 counter;				/* assignment counter */
	SEMM_ID mutex;				/* mutex */
	unsigned char* data;			/* pointer to string */
	FUNCPTR FuncUpdateString;		/* pointer to callback function */
	INT32 FuncUpdateStringParam;		/* parameter of callback function */
} SYS_STRING;

在接收字符串的C函数的声明中,指定字符串参数:

int MY_C_FUNCTION(int some_var, SYS_STRING* some_str)

在将从MC-Basic到C函数的接口声明的import_c命令中,声明:

import_c MY_C_FUNCTION(byval as long, byval as string) as long


从共享对象中使用Linux sys.log

为了可以在Linux logger sys.log中记录消息,你需要在代码中加入以下声明::

/**************************    Linux sys.log Declarations    ******************************/

/* MC Modules */
#define MODULE_NON	 	 0
#define MODULE_MOTION		 1
#define MODULE_RTS		 2
#define MODULE_TRANSLAT		 3
#define MODULE_SERCOS		 4
#define MODULE_ROBOT		 5
#define MODULE_TRACER		 6
#define MODULE_SYSTEM		 7
#define MODULE_MEMORY		 8
#define MODULE_FILE_SYSTEM	 9
#define MODULE_CLI		10
#define MODULE_RBOOTP		11
#define MODULE_ETHERCAT		12
#define MODULE_FASTDATA		13
#define MODULE_UAC		14
#define MODULE_MC_BASIC		15
#define MODULE_CANOPEN		16


/* MC Log Level */
#define LOG_LEVEL_NON		0
#define LOG_LEVEL_ERROR		1
#define LOG_LEVEL_WARNING	2
#define LOG_LEVEL_NOTE		3
#define LOG_LEVEL_DEBUG		4
#define LOG_LEVEL_ALL		5

extern int sys_log(int sub_system, int _debug_level, const char * fmt, int arg1, int arg2,
			int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10);

/******************************************************************************************/

要发送一条消息到sys.log调用sys_log与fmt作为一个printf格式的字符串。 有关sys.log和一个例子的更全面的解释可以在Linux sys.log.中找到。


下载

提取Shared_Object.ZIP以查找上述示例
File:Shared Object.zip

该示例对应于在GIT中的提交的SHA-1: 5228016ac44122213dcb05d781b15c8e05054d5b in GIT.


参见