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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux c++ 怎么 调用自己函数的相关的知识,希望对你有一定的参考价值。

实验平台: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 -setup Options 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 is placed 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 MATLAB variables with more than 2^32-1 elements. In the near future you will be required to update your code to utilize the new API. 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 command options, and the runtime libraries to link against. Using the \'mbuild -setup\' command selects an options file that is placed 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+B;end

(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 std;int 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 lib libmyFuncTerminate(); // terminate MCR mclTerminateApplication(); 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

源代码及编译过程中的所有文件已打包,点击这里可以下载。
参考技术A 可能是这样,a.cpp,a.h在文件夹f1中,b.cpp,b.h在文件夹2中,c.cpp,c.h也在文件夹1中,按你说的,a.cpp中引用了一个b.cpp中的函数,但是a.cpp和a.h中都没有找到对应的函数声明,那么有可能是这样,a.h引用了b.h,而b.h又引用了c.h。

a.cpp中的fun1()要在b.cpp中使用,那么其实可以这样,在b.cpp中使用fun1()之前,先声明下fun1(),前提是b.cpp要包含a.cpp的头文件并且fun1()也在a.cpp的头文件中声明。

C#调用C++ dll 回调

c++原文定义:
回调函数,const char *strPerc为内部字符指针,回调函数返回测量数据
typedef void (*PercCallback)(const char *strPerc);
//注册回调函数
extern "C" _declspec(dllexport) void RegisterPercCallback(PercCallback Callback);
——————————————————————————————————————
我自己写的C#:
[DllImport("PR202_10Dll.dll", CharSet = CharSet.Auto, EntryPoint = "RegisterPercCallback", CallingConvention = CallingConvention.Cdecl)]
public static extern Boolean RegisterPercCallback(PercCallback Callback);
public delegate void PercCallback([MarshalAs(UnmanagedType.LPArray, SizeConst = 8000)]byte[] msg);
想显示 回调信息。该怎么下下面的语句?

参考技术A C#调用于windows平台或其他内部之类的调用,叫PInvoke或P-Invoke(Platform invoke,平台调用),有关这部分的知识在MSDN上描写的很详细的。涉及到的内容就是所谓的“平台封送”的问题,它并非简的类型对照,所有这方面的知识需要去MSDN上查询有关PInvoke的内容。
就目前来看,楼主所谓的以上两个定义基本上来说是正确的(其实回调用函数封送时也可以考虑使用StringBuilder去接收的),但这两个句代码只是表示你“定义”了调用,在没有调用时显然是不行的。所以你需要写委托对应的方式写完整,然后在调用主函数(RegisterPercCallback)即可。委托自会调用相应的方法。
所以你这里只是声明了委托,但委托真正的方法还没有写完。第一部分在入口或程序执行过程中执行平台调用的方法,该方面调用时会调用C++中的对应的方法(EntryPoint指明的方法,如果没有EntryPoint则使用的是同名方法),并加入委托(平台封送的委托也是正确的)。
其实在调用时与你正常程序的调用是一样的。只是必须使用static extent C来说明真正的平台调用而已,你写的声明其实真正的实现是在C中EntryPoint实现的,而委托其实只是被最终封送成指针到C中了!追问

非常感谢您的指点,下午摸索了一下。通过private void getdata()



callback = CallBackFunction;

RegisterPercCallback(callback);


取到了数据,但是又有保存。这块能麻烦您再指点一下吗?

报错。

另外,c++ const char*在c#中到底用什么代替呢?string 还是byte[]?现在是用string取到的。

追答

都能取出来数据,你还在乎保存什么的吗?平台调用初始情况经常会出现一些内存无法读取等情况的。这是因为你回调方法中不能直接操作封送数据的,因为封送数据并不是你真正的数据。也就是说如果你试图对byte[](那个封送数据进行写入的话往往是内存无法读写的错误)。如果你使用的是StringBuilder进行封送的话,也不能直接操作StringBuilder的。
只要注意封送的数据不去操作就可以了,所以你能显示出来的时候,那个值保存起来又有什么关系?

追问

是报错,打错打成保存了。

数据显示后点击确定就报错了。

追答

那么你又不给出代码,exception是能抛到最外面,所以就把最外层的代码让我看什么?把引用错误的代码发出来才能看到啊。又一个对Exception机制不熟悉的。

追问

代码贴不下,麻烦移步到csdn:http://bbs.csdn.net/wap/topics/392159585

麻烦您看看!

追答

原因我已经解释很清楚了,既然执行过ReadLastData怎么还会再去读取Byte呢?还有,你是哪个vs版本?我记着没错的错Byte[] m = new byte[]; m.ToString()的返回值应该是"System.Bytes",而如果是string类型的话,string.ToString()本身就是多余,若没值的话也会存在null.ToString()的空引用错误(System.ArgumentNullException),所以你的代码看起来本身就不对的。ReadLastData已经读取数据了,所以委托应该会自行被调用,而不是直接由程序调用的,否则委托还叫什么委托(委托的意思就是让其他程序委托执行,说白了是指针,其实有点象友元函数的概念)。所以应该是你重复执行了。你可以调用试一下!
顺便说一下,如果你的程序是专用驱动的话这种方案的选择是正确的。而如果是免驱(由windows自身提供驱动)的话,你要么直接调用windows底层(PInvoke)而不该直接调用人家的应该程序中的(免驱的意思是标准的windows驱动,你pinvoke到人家应该程序还不如直接使用tbl工具的方案,专用程序常用这个方案),粗看下来,基本上SerialPort通信,如果有通信参数的话应该使用SerialPort方式开发。所以我有点怀疑你不是选错开发方案了?

追问

原来代码是byte,后修改为String了。这个是个农残检测仪,没有sdk,只有个C++做的dll和一个简单的文档说明。看您这么说我觉得就是重复调用引起的报错,那么ReadLastData()是必须的,自定义的getdata这里如何处理才能避免重复调用呢?

ReadLastData是dll中定义用来取最后一次数据的,数据又需要通过回调才能输出,其实就是矛盾在执行ReadLastData后怎么才能把回调数据显示出来?

用的版本是vs2017 ,我自学的c#,基础不好,唯一的一点基础是au3和易语言。。。非常感谢您精彩的指导。给您添麻烦了!!

本回答被提问者和网友采纳

以上是关于linux c++ 怎么 调用自己函数的的主要内容,如果未能解决你的问题,请参考以下文章

C/C++ C++调用用C库函数理解

c++ 类的复制函数

C++中的派生类,可以不定义对象直接调用基类的成员和调用自己的成员函数嘛???

(74)C#里怎么样调用WIN API的函数时实现回调函数

C++中CFile open函数怎么创建不了文件

在 Linux 中从 C++ 库调用 C++ 函数