文选流氓 发表于 2004-6-2 23:34

Mathematica 和 C/C++的混合编程 ZT

发信人: observer (笑看人生), 信区: Science
标 题: mathematica 和 C/C++的混合编程 -observer
发信站: Unknown Space - 未名空间 (Thu May 27 14:49:38 2004), 转信

网上已经有matlab 和 c的混合编程,

我就来写个mathematica 和 C/C++的混合编程吧,只图方便

- observer

mathematica的数学运算在有些方面比 matlab 要全一些,symbolic computing就不
用说了,

比如我感兴趣的 non-square的矩阵求逆, mathematica可以直接做,

matlab还要自己调svd,剔除无效singular value,再算逆矩阵,

还有spherical harmonics,mathematica 可以直接求

当然matlab和mathematica 我两个都用,

我比较喜欢的是用mathematica和matlab完成那些公式函数太多的运算,

调函数的方式在matlab和mathematica下效率是优化过的,所以不慢

而剩下的“苦”活就由我用c/c++来写好了

以下基于mathematica 5.0 的 mathlink 和 VC6,

mathlink支持很多接口,包括tcp/ip, 也就是装mathematica的机器可以不在本地

mathematica 好象没有做成 matlab那样,可以直接调用dll

而是用一个 mathlink的c/c++ 接口,即你的程序只和mathlink建立连接,

由mathlink启动mathematica kernal并将结果返回给你。

也就是说当你调用mathmatic函数时,mathematica主程序是单独运行的

(1) 先配置vc 的ide

把mathematica 为 vc写的include, lib, bin 目录加到 vc->tools->directories
, 怎么加不用说了吧

mathematica 的这些目录缺省在

C:Program FilesWolfram ResearchMathematica.0AddOnsMathLinkDevelo
perKitWindowsCompilerAdditionsMLDev32

(2) 在你的vc project->settings->link->library modules下加入mathematica 的
lib文件"ML32I2M.LIB"

否则link你的程序时那些接口函数会找不到地

别的编译器也有mathematica提供的类似的lib文件,就不多说了

至于dll文件在你装mathematica时就设置好了,不用操心

(3) 在你的接口程序中 include mathlink的头文件"mathlink.h"

下面来分两种情况说混合编程

1. C/C++ 中调用mathematica

例子是从 help doc里面改出来的,运行通过

唯一要说明的是当建立mathlink时提示要找的exe是mathematica的keneral

而不是你自己程序编译出来的exe

如果参数用

-linkname "mathematica 的 kernal程序的完整路径"

可以省却每次都去找路径的麻烦

/* To run this program use the command-line below:

*      Unix:         quotient -linkname "math -mathlink"

*      Mac or Windows: quotient -linkmode launch

*/

#include <stdio.h>

#include <stdlib.h>

#include "mathlink.h"

extern int mlmactty_init( char*** argvp);

static void init_and_openlink( int argc, char* argv[]);

MLENV ep = (MLENV)0;

MLINK lp = (MLINK)0;

int main( int argc, char* argv[])

{

         int pkt, m, n, q;

         init_and_openlink( argc, argv);

         

         MLActivate(lp);

//      printf( "Two integers m/n: ");

//      if( scanf( "%d/%d", &m, &n) != 2 && scanf( "%d %d", &m, &n) != 2)

//            exit(-1);

         m = 4;

         n = 2;

         /* Send EvaluatePacket[ Quotient[ m, n]] */

         MLPutFunction( lp, "EvaluatePacket", 1L);

               MLPutFunction( lp, "Quotient", 2L);

                         MLPutInteger( lp, m);

                         MLPutInteger( lp, n);

         MLEndPacket( lp);

         

         /* skip any packets before the first ReturnPacket */

         while( (pkt = MLNextPacket( lp), pkt) && pkt != RETURNPKT)

               MLNewPacket( lp);

         

         /* inside the ReturnPacket we expect an integer */

         MLGetInteger( lp, &q);

         

         printf( "quotient = %d ", q);

         

         /* quit Mathematica */

         MLPutFunction( lp, "Exit", 0);

         return 0;

}

static void deinit( void)

{

         if( ep) MLDeinitialize( ep);

}

static void closelink( void)

{

         if( lp) MLClose( lp);

}

static void init_and_openlink( int argc, char* argv[])

{

         long err;

#if MACINTOSH_MATHLINK

         MLYieldFunctionObject yielder;

         argc = mlmactty_init( &argv);

#endif

         ep =MLInitialize( (MLParametersPointer)0);

         if( ep == (MLENV)0) exit(1);

         atexit( deinit);

#if MACINTOSH_MATHLINK

         yielder = MLCreateYieldFunction( ep, NewMLYielderProc( MLDefaultYielder
, 0);

#endif

         lp = MLOpenArgv( ep, argv, argv + argc, &err);

         if(lp == (MLINK)0) exit(2);

         atexit( closelink);

         

#if MACINTOSH_MATHLINK

         MLSetYieldFunction( lp, yielder);

#endif

}


上面程序用几个接口函数将命令传给mathlink, 再从mathlink得到结果

命令具体格式和含义就看help 吧

(2) mathematica 调 c/c++

这个呢就比上面稍微麻烦一点

以mathematica 提供的例子 addtwo 为例

(缺省在C:Program FilesWolfram ResearchMathematica.0AddOnsMathLin
kDeveloperKitWindowsMathLinkExamples"下可以找到)

值得注意的是为了调用c/c++写的函数,需要声明该函数在mathematica里面的接口


就是如文件addtwo.tm所示的东西

int addtwo P(( int, int));

: Begin:

: Function:       addtwo

: Pattern:      AddTwo

: Arguments:      { i, j }

: ArgumentTypes:{ Integer, Integer }

: ReturnType:   Integer

: End:

: Evaluate: AddTwo::usage = "AddTwo gives the sum of two machine in
tegers x and y."
   
然后用 前面提到的 bin 目录下的MPREP.EXE生成接口申明的addtwotm.c文件,

和addtwo.c的源c文件一块编译

注意,生成addtwotm.c这一步可以用vc ide 的custom build 完成即

include addtwo.tm 到你的project中去

project->setting->custom build->

在左边文件列表中选addtwo.tm, 在右边的commands中填入

mprep addtwo.tm -o addtwotm.c

在右边的ouput中填入

$(OutDir)addtwotm.c

第一次编译时就会在debug目录下输出addtwotm.c文件

include it 到你的project中,就可以编译通过了

运行时到mathematica中,

link = Install];

就会要你找到该外部命令的exe,也就是刚刚编译出来的exe

剩下的就是在mathematica中敲

AddTwo之类的运行该命令了

网上URL:

www.mathematica.com

http://documents.wolfram.com/v5/Add-onsLinks/MathLink/System-SpecificInf ormation/Windows/index.html

上面的例子我都运行通过了,如果我有什么遗漏,欢迎指正

嗯,版权归observer所有

--
※ 来源:.Unknown Space - 未名空间 mitbbs.com.

(按:呵呵,Mathematica Dos版是我上大学用的第一个数学计算软件,不过后来基本使用Matlab啦。存个目,以防万一吧)

雪无痕 发表于 2004-6-4 12:43

YOHO~打个招呼~
老流氓还在不?
为啥我本来有3000多贴,现在就这么点点啦?
这里一堆人我不认识了。。。昏。。。

路路 发表于 2004-6-4 13:12

时过境迁,物是人非。

文选流氓 发表于 2004-6-4 13:13

最初由 雪无痕 发布
YOHO~打个招呼~
老流氓还在不?
为啥我本来有3000多贴,现在就这么点点啦?
这里一堆人我不认识了。。。昏。。。
估计你以前灌水太多,被斑竹们收拾了吧。嘿嘿。
页: [1]
查看完整版本: Mathematica 和 C/C++的混合编程 ZT