linux c++ 怎么 调用自己函数的

linux c++ 怎么 调用自己函数的,第1张

实验平台:ubuntu 12.04 + g++4.6 + matlab2012a

问题描述:

有一个c++程序main.cpp,和一个matlab函数myFunc.m。现在要做这件事:

1)从main.cpp中传递2个double类型的数值a和b到myFunc.m中

2)myFunc.m中求和(sum = a+b)

3)main.cpp中接收myFunc.m返回的和并输出。

思路:

1)设置matlab的编译器,使用gcc编译器。编译m文件成.so。

2)编译.cpp文件,编译时调用.so库(添加.so的路径到编译选项)。

步骤:

1)将自己的matlab函数(myFunc.m)编译成动态链接库

(1) 设定编译器为gcc,在matlab 命令行依次执行命令mex -setup和mbuild -setup:

>>mex -setupOptions files control which compiler to use, the compiler and link command options, and the runtime libraries to link against.Using the 'mex -setup' command selects an options file that isplaced in ~/.matlab/R2012a and used by default for 'mex'. An options file in the current working directory or specified on the command line overrides the default options file in ~/.matlab/R2012a. To override the default options file, use the 'mex -f' command(see 'mex -help' for more information).The options files available for mex are: 1: /opt/MATLAB/R2012a/bin/mexopts.sh : Template Options file for building gcc MEX-files 0: Exit with no changesEnter the number of the compiler (0-1):1/opt/MATLAB/R2012a/bin/mexopts.sh is being copied to ~/.matlab/R2012a/mexopts.shcp: cannot create regular file `~/.matlab/R2012a/mexopts.sh': Permission denied************************************************************************** Warning: The MATLAB C and Fortran API has changed to support MATLABvariables with more than 2^32-1 elements. In the near futureyou will be required to update your code to utilize the newAPI. You can find more information about this at:http://www.mathworks.com/help/techdoc/matlab_external/bsflnue-1.html Building with the -largeArrayDims option enables the new API. **************************************************************************>>mbuild -setup Options files control which compiler to use, the compiler and link commandoptions, and the runtime libraries to link against.Using the 'mbuild -setup' command selects an options file that isplaced in ~/.matlab/R2012a and used by default for 'mbuild'. An options file in the current working directory or specified on the command line overrides the default options file in ~/.matlab/R2012a. To override the default options file, use the 'mbuild -f' command (see 'mbuild -help' for more information).The options files available for mbuild are: 1: /opt/MATLAB/R2012a/bin/mbuildopts.sh : Build and link with MATLAB Compiler generated library via the system ANSI C/C++ compiler 0: Exit with no changesEnter the number of the compiler (0-1):1/opt/MATLAB/R2012a/bin/mbuildopts.sh is being copied to ~/.matlab/R2012a/mbuildopts.shcp: cannot create regular file `~/.matlab/R2012a/mbuildopts.sh': Permission denied>>

(2) 在matlab中,编写myFunc.m文件内容如下:

function [ C ] = myFunc(A, B)C = A+Bend

(3) 生成myFunc.m的动态链接库(.so)

>>mcc -W cpplib:libmyFunc -T link:lib myFunc.m -cWarning: MATLAB Toolbox Path Cache is out of date and is not being used.Type 'help toolbox_path_cache' for more info >>

等待数秒,完成。可以看到myFunc.m所在的目录下生成了多个文件:

$ lslibmyFunc.cpp libmyFunc.ctf libmyFunc.exports libmyFunc.h libmyFunc.so main.cpp mccExcludedFiles.log myFunc.m readme.txt

令解释:其中-W是控制编译之后的封装格式;cpplib是指编译成C++的lib;cpplib冒号后面是指编译的库的名字;-T表示目

标,link:lib表示要连接到一个库文件的目标,目标的名字即是.m函数的名字。-c表明需要生成.ctf文件,比如本例如果不加-c就不会生成

“libmyFunc.ctf”。

生成的文件中打开“libmyFunc.h”可以看到一行:

extern LIB_libmyFunc_CPP_API void MW_CALL_CONV myFunc(int nargout, mwArray&C, const mwArray&A, const mwArray&B)

个就是我们的myFunc.c函数待会儿在c++中调用时的接口。有4个参数,第一个是参数个数,第二个是用来接收函数返回值的,后面2个是从c++中传

递进来的变量。我们还会用到“libmyFunc.h”中的另外2个函数:libmyFuncInitialize()初始化,和注销

libmyFuncTerminate()。

2)编写main.cpp,代码如下:

#include <iostream>#include "mclmcr.h"#include "matrix.h"#include "mclcppclass.h"#include "libmyFunc.h"#include "mclmcrrt.h"using namespace stdint main() {// initialize lib,这里必须做初始化!if( !libmyFuncInitialize()){std::cout <<"Could not initialize libmyFunc!" <<std::endl return -1 }// 用户输入2个数值double a, b cout<<"Please input 2 numbers <a b>and then press enter: "<<endl cin >>a cin >>b double c//used to receive the result// 为变量分配内存空间, maltab只有一种变量,就是矩阵,为了和c++变量接轨,设置成1*1的矩阵mwArray mwA(1, 1, mxDOUBLE_CLASS)//1,1表示矩阵的大小, mxDOUBLE_CLASS表示变量的精度mwArray mwB(1, 1, mxDOUBLE_CLASS) mwArray mwC(1, 1, mxDOUBLE_CLASS) // 调用类里面的SetData函数给类赋值mwA.SetData(&a, 1) mwB.SetData(&b, 1) // 调用自己的函数,求和。myFunc(1, mwC, mwA, mwB) c = mwC.Get(1, 1) cout<<"The sum is: "<<c<<endl // 后面是一些终止调用的程序// terminate the liblibmyFuncTerminate() // terminate MCRmclTerminateApplication() return EXIT_SUCCESS}

3)编译main.cpp函数,调用libmyFunc.so

$ g++ -o main -I. -I/opt/MATLAB/R2012a/extern/include -L. -L/opt/MATLAB/R2012a/runtime/glnxa64 main.cpp -lmyFunc -lm -lmwmclmcrrt -lmwmclmcr

开始编译时也遇到一些问题,主要是链接库路径问题导致的编译错误,详细错误汇总在另篇笔记里(点此查看)。

编译成功后,需要装一下MCR Installer,步骤点此。

运行结果:

$ ./main Warning: latest version of matlab app-defaults file not found.Contact your system administrator to have this file installedPlease input 2 numbers <a b>and then press enter: 10 100The sum is: 110$ ./main Warning: latest version of matlab app-defaults file not found.Contact your system administrator to have this file installedPlease input 2 numbers <a b>and then press enter: 1 1The sum is: 2

源代码及编译过程中的所有文件已打包,点击这里可以下载。

1:通常export该函数。

2:获取结构体指针:在driver设个全局变量。

下面贴出自己写的xenon

flash

driver部分代码。

struct

xenon_flash_chip

{

struct

i2c_client

*xenon_flash_client

}

static

struct

xenon_flash_chip

*xenon_chip

//this

is

just

for

debug

int

xenon_flash_reread(void)

{

int

err

=

0

u8

data

struct

xenon_flash_chip

*chip

if(xenon_chip==NULL)

return

err

chip=xenon_chip

//read

07

err

=

xenon_flash_i2c_read(chip->xenon_flash_client,0x07,&data)

if

(err

<

0)

return

err

CDBG("[xenon_flash]reg_control

reg=0x07

data=0x0%x\n",data)

//read

06

err

=

xenon_flash_i2c_read(chip->xenon_flash_client,0x06,&data)

if

(err

<

0)

return

err

CDBG("[xenon_flash]reg_control

reg=0x06

data=0x0%x\n",data)

//read

04

err

=

xenon_flash_i2c_read(chip->xenon_flash_client,0x04,&data)

if

(err

<

0)

return

err

CDBG("[xenon_flash]reg_control

reg=0x04

data=0x0%x\n",data)

return

err

}

EXPORT_SYMBOL(xenon_flash_reread)

static

int

__devinit

xenon_flash_i2c_probe(struct

i2c_client

*client,

const

struct

i2c_device_id

*id)

{

int

rc

=

0

static

const

u32

i2c_funcs

=

I2C_FUNC_SMBUS_BYTE_DATA

|

I2C_FUNC_SMBUS_WRITE_WORD_DATA

struct

xenon_flash_chip

*chip

struct

xenon_flash_platform_data

*pdata

CDBG("xenon_flash_i2c_probe

called!\n")

/*

check

*/

if

(client->dev.platform_data

==

NULL)

{

dev_err(&client->dev,

"xenon_flash

platform

data

is

NULL.

exiting.\n")

return

-ENODEV

}

/*

Copy

to

global

variable

*/

pdata

=

client->dev.platform_data

/*check

i2c

func*/

if

(!i2c_check_functionality(client->adapter,

i2c_funcs))

return

-ENOSYS

/*

Allocate

memory

for

driver

data

*/

chip

=

kzalloc(sizeof(struct

xenon_flash_chip),

GFP_KERNEL)

if

(!chip)

return

-ENOMEM

xenon_chip

=

chip

i2c_set_clientdata(client,chip)

chip->xenon_flash_client

=

client

rc

=

xenon_flash_init_hw(chip,pdata)

if

(rc

<

0)

CDBG("xenon_flash_init_hw

initlised

failed!\n")

return

0

}

在driver调试过程中,通常需要将关键函数export出来,在其他地方extern声明再调用调试。

注意看这个文件

sysdeps/unix/sysv/linux/syscalls.list

里面记录着系统调用的名字和一些属性,具体我也没有研究过,不懂。

再看select的实现,很让人惊讶,一旦使用,结果就是“报错“。

int

__select (nfds, readfds, writefds, exceptfds, timeout)

int nfds

fd_set *readfds

fd_set *writefds

fd_set *exceptfds

struct timeval *timeout

{

__set_errno (ENOSYS)

return -1

}

libc_hidden_def (__select)

stub_warning (select)

weak_alias (__select, select)

这是因为glibc并没有实现系统调用,而是调用系统调用,

更进一步,连调用系统调用都没有一个个实现,而是使用了通用的办法,

理由很简单,所有的系统调用在linux内核头文件里都能找到,

所有的系统调用参数类型就那么几种,参数个数也是有限的,

因此没有必要针对所有的系统调用一一封装,

于是就有了这个list文件,自动生成调用系统调用的函数,

如果生成失败,也就是你看到的“报错”。

符号是有强弱的,当自动生成成功的时候,“报错”的弱符号就被忽略了。

当你在glibc中找到一个系统调用的封装源码,是以下原因,

1. 编译的目标系统不支持这个系统调用,所以自己用另一种方式实现了。

2. 这个系统调用无法使用通用的自动生成方式生成,用特化的方式覆盖。

3. 针对这个系统调用做了特别的优化。

4. 其它可能的原因。

具体可以留意

SYSCALL, PSEUDO, DO_CALL, INLINE_CALL 等名字

这两个文件是重点所在

sysdeps/unix/i386/sysdep.h

sysdeps/unix/i386/sysdep.S

要搞清楚具体的自动生成过程,恐怕得研究glibc自身的编译过程了


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/8633268.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-19
下一篇2023-04-19

发表评论

登录后才能评论

评论列表(0条)

    保存