- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想我开始了解如何将用 C/C++ 编写的函数链接到 Mathematica。我面临的问题是我不知道如何从我的 C 包装器向 Mathematica 发送错误消息。在谷歌搜索后,我找到了这个 MathLink Tutorial .
第 1.7 节让我深入了解如何发送错误消息,但我得到了奇怪的结果。这是我正在使用的代码。
//File cppFunctions.h
#ifndef CPPFUNCTIONS_H
#define CPPFUNCTIONS_H
class Point {
public:
double x, y;
Point(){ x=y=0.0;}
Point(double a, double b): x(a), y(b) {}
};
class Line {
public:
Point p1, p2;
Line(void) {}
Line(const Point &P, const Point &Q): p1(P), p2(Q) {}
double distanceTo(const Line &M, const double &EPS = 0.000001){
double x21 = p2.x - p1.x; double y21 = p2.y - p1.y;
double x43 = M.p2.x - M.p1.x; double y43 = M.p2.y - M.p1.y;
double x13 = p1.x - M.p1.x; double y13 = p1.y - M.p1.y;
double den = y43*x21 - x43*y21;
if (den*den < EPS) return -INFINITY;
double numL = (x43*y13 - y43*x13)/den;
double numM = (x21*y13 - y21*x13)/den;
if (numM < 0 || numM > 1) return -INFINITY;
return numL;
}
};
#endif
Point
和
Line
.除了我想在 Mathematica 中使用的函数之外,我已经将这个类剥离到最低限度。我想找到从一条线到另一条线的距离。这个函数是
lineInt
的C版本在
wireframes in Mathematica .要在 Mathematica 中使用这个函数,我们需要一个包装函数,它从 Mathematica 获取输入并将输出发送回 Mathematica。
//mlwrapper.cpp
#include "mathlink.h"
#include <math.h>
#include "cppFunctions.h"
void ML_GetPoint(Point &P){
long n;
MLCheckFunction(stdlink, "List", &n);
MLGetReal64(stdlink, &P.x);
MLGetReal64(stdlink, &P.y);
}
void ML_GetLine(Line &L){
long n;
MLCheckFunction(stdlink, "List", &n);
ML_GetPoint(L.p1);
ML_GetPoint(L.p2);
}
double LineDistance(void) {
Line L, M;
ML_GetLine(L);
ML_GetLine(M);
return L.distanceTo(M);
}
int main(int argc, char* argv[]) {
return MLMain(argc, argv);
}
ML_GetPoint
和
ML_GetLine
帮助我从 Mathematica 获取输入。从包含两个列表的列表中获取一行。每个子列表都是 2 个实数(一个点)的列表。要在 Mathematica 中尝试此功能,我们需要更多文件。
//mlwrapper.tm
double LineDistance P((void));
:Begin:
:Function: LineDistance
:Pattern: LineDistance[L_List, M_List]
:Arguments: {L, M}
:ArgumentTypes: {Manual}
:ReturnType: Real
:End:
:Evaluate: LineDistance::usage = "LineDistance[{{x1,y1}, {x2,y2}}, {{x3,y3}, {x4,y4}}] gives the distance between two lines."
:Evaluate: LineDistance::mlink = "There has been a low-level MathLink error. The message is: `1`"
Evaluate
声明
usage
的功能。当
?LineDistance
时,它会给出有关该功能的简短消息。被输入到 Mathematica。其他
Evaluate
是我希望在出现错误时使用的那个(稍后会详细介绍)。
#Makefile
VERSION=8.0
MLINKDIR = .
SYS = MacOSX-x86-64
CADDSDIR = /Applications/Mathematica.app/SystemFiles/Links/MathLink/DeveloperKit/CompilerAdditions
INCDIR = ${CADDSDIR}
LIBDIR = ${CADDSDIR}
MPREP = ${CADDSDIR}/mprep
RM = rm
CXX = g++
BINARIES = mlwrapper
all : $(BINARIES)
mlwrapper : mlwrappertm.o mlwrapper.o
${CXX} -I${INCDIR} mlwrappertm.o mlwrapper.o -L${LIBDIR} -lMLi3 -lstdc++ -framework Foundation -o $@
.cpp.o :
${CXX} -c -I${INCDIR} $<
mlwrappertm.cpp : mlwrapper.tm
${MPREP} $? -o $@
clean :
@ ${RM} -rf *.o *tm.c mlwrappertm.cpp
make > makelog.txt
make clean
mlwrapper
.现在我们可以开始使用 Mathematica:
SetDirectory[NotebookDirectory[]];
link = Install["mlwrapper"];
?LineDistance
Manipulate[
Grid[{{
Graphics[{
Line[{p1, p2}, VertexColors -> {Red, Red}],
Line[{p3, p4}]
},
PlotRange -> 3, Axes -> True],
LineDistance[{p1, p2}, {p3, p4}]
}}],
{{p1, {-1, 1}}, Locator, Appearance -> "L1"},
{{p2, {2, 1}}, Locator, Appearance -> "L2"},
{{p3, {2, -2}}, Locator, Appearance -> "M1"},
{{p4, {2, 3}}, Locator, Appearance -> "M2"}
LineDistance[{{0, 0}, {0}}, {{1, -1}, {1, 1}}]
$Failed
.以下情况如何:
LineDistance[{{1, -1}, {1, 1}}]
LineDistance[{{1, -1}, {1, 1}}]
.我猜这是因为我们在
Pattern
中描述过
.tm
的部分该函数接受两个列表,因为我们只给出了一个列表,所以它与模式不匹配。这是真的?
#include "mathlink.h"
#include <math.h>
#include <string>
#include "cppFunctions.h"
bool ML_Attempt(int func, const char* err_tag){
if (!func) {
char err_msg[100];
sprintf(err_msg, "Message[%s,\"%.76s\"]", err_tag, MLErrorMessage(stdlink));
MLClearError(stdlink); MLNewPacket(stdlink); MLEvaluate(stdlink, err_msg);
MLNextPacket(stdlink); MLNewPacket(stdlink); MLPutSymbol(stdlink, "$Failed");
return false;
}
return true;
}
void ML_GetPoint(Point &P){
long n;
if(!ML_Attempt(MLCheckFunction(stdlink, "List", &n), "LineDistance::mlink2"))return;
if(!ML_Attempt(MLGetReal64(stdlink, &P.x), "LineDistance::mlink3")) return;
if(!ML_Attempt(MLGetReal64(stdlink, &P.y), "LineDistance::mlink4")) return;
}
void ML_GetLine(Line &L){
long n;
if(!ML_Attempt(MLCheckFunction(stdlink, "List", &n), "LineDistance::mlink1"))return;
ML_GetPoint(L.p1);
ML_GetPoint(L.p2);
}
double LineDistance(void) {
Line L, M;
ML_GetLine(L);
ML_GetLine(M);
return L.distanceTo(M);
}
int main(int argc, char* argv[]) {
return MLMain(argc, argv);
}
:Evaluate: LineDistance::mlink1 = "There has been a low-level MathLink error. The message is: `1`"
:Evaluate: LineDistance::mlink2 = "There has been a low-level MathLink error. The message is: `1`"
:Evaluate: LineDistance::mlink3 = "There has been a low-level MathLink error. The message is: `1`"
:Evaluate: LineDistance::mlink4 = "There has been a low-level MathLink error. The message is: `1`"
ML_Attempt
中的任何其他 ML 函数而我只使用
MLEvaluate
发送错误标签,然后 MathLink 损坏,我必须重新安装链接。有谁知道如何从 C 向 Mathematica 发送错误消息?
exit
功能。我们可以做类似的事情吗?如果我们使用
exit
功能链接将被破坏,我们将不得不重新安装该功能。取函数
ML_GetPoint
和
ML_GetLine
例如。如果此处发生错误,则在主函数
LineDistance
中进行计算没有意义。 .我们需要清除我们获得的任何错误,向 Mathematica 发送一条消息,指明错误,现在退出并等待下一次调用。
最佳答案
作为@ragfield 解决方案的替代方案,您可以将函数声明为 void
并手动返回结果。这是基于 addTwo
的示例标准示例。这是模板:
void addtwo P(( int, int));
:Begin:
:Function: addtwo
:Pattern: AddTwo[i_Integer, j_Integer]
:Arguments: { i, j }
:ArgumentTypes: { Integer, Integer }
:ReturnType: Manual
:End:
:Evaluate: AddTwo::usage = "AddTwo[x, y] gives the sum of two machine
integers x and y."
:Evaluate: AddTwo::badargs = "Arguments are expected to be positive numbers"
void addtwo( int i, int j) {
if(i>0&&j>0){
MLPutInteger(stdlink,i+j);
}else{
MLPutFunction(stdlink,"CompoundExpression",2);
MLPutFunction(stdlink,"Message",1);
MLPutFunction(stdlink,"MessageName",2);
MLPutSymbol(stdlink,"AddTwo");
MLPutString(stdlink,"badargs");
MLPutSymbol(stdlink,"$Failed");
}
}
In[16]:= AddTwo[1,2]
Out[16]= 3
In[17]:= AddTwo[-1,2]
During evaluation of In[17]:= AddTwo::badargs: Arguments are expected
to be positive numbers
Out[17]= $Failed
extern void addeight( void );
extern void addall(void);
static void putErrorMessageAndReturnFailure(const char *fname, const char *msgtag);
void addeight(void)
{
int i,j,k,l,i1,j1,k1,l1;
MLGetInteger(stdlink,&i);
MLGetInteger(stdlink,&j);
MLGetInteger(stdlink,&k);
MLGetInteger(stdlink,&l);
MLGetInteger(stdlink,&i1);
MLGetInteger(stdlink,&j1);
MLGetInteger(stdlink,&k1);
MLGetInteger(stdlink,&l1);
if(i<0||j<0||k<0||l<0||i1<0||j1<0||k1<0||l1<0){
putErrorMessageAndReturnFailure("AddEight","badargs");
}else{
MLPutFunction(stdlink,"List",2);
MLPutFunction(stdlink,"List",2);
MLPutInteger(stdlink,i+i1);
MLPutInteger(stdlink,j+j1);
MLPutFunction(stdlink,"List",2);
MLPutInteger(stdlink,k+k1);
MLPutInteger(stdlink,l+l1);
}
}
void addall(){
int *data, len, i = 0,sum = 0;
if(!MLGetIntegerList(stdlink, &data, &len)){
putErrorMessageAndReturnFailure("AddAll","interr");
return;
}
for(i=0;i<len;i++){
if(data[i]<0){
putErrorMessageAndReturnFailure("AddAll","badargs");
return;
}else{
sum+=data[i];
}
}
MLPutInteger(stdlink,sum);
MLReleaseInteger32List(stdlink, data, len);
}
static void putErrorMessageAndReturnFailure(const char *fname, const char *msgtag){
MLPutFunction(stdlink,"CompoundExpression",2);
MLPutFunction(stdlink,"Message",1);
MLPutFunction(stdlink,"MessageName",2);
MLPutSymbol(stdlink,fname);
MLPutString(stdlink,msgtag);
MLPutSymbol(stdlink,"$Failed");
}
void addeight P(( ));
:Begin:
:Function: addeight
:Pattern: AddEight[{{i_Integer, j_Integer},{k_Integer,l_Integer}},{{i1_Integer,j1_Integer},{k1_Integer,l1_Integer}}]
:Arguments: { i, j, k ,l, i1,j1,k1,l1 }
:ArgumentTypes: { Manual }
:ReturnType: Manual
:End:
:Evaluate: AddEight::usage = "AddEight[{{i_Integer, j_Integer},{k_Integer,l_Integer}}, {{i1_Integer, j1_Integer},{k1_Integer,l1_Integer}}] gives the sum as a list: {{i+i1,j+j1},{k+k1,l+l1}}."
:Evaluate: AddEight::badargs = "Arguments are expected to be positive numbers"
void addall P(( ));
:Begin:
:Function: addall
:Pattern: AddAll[fst:{{_Integer, _Integer},{_Integer,_Integer}},sec:{{_Integer, _Integer},{_Integer,_Integer}}]
:Arguments: { Flatten[{fst,sec}]}
:ArgumentTypes: { Manual }
:ReturnType: Manual
:End:
:Evaluate: AddAll::usage = "AddAll[{{i_Integer, j_Integer},{k_Integer,l_Integer}},{{i1_Integer, j1_Integer},{k1_Integer,l1_Integer}}] gives the total sum of elemens of the sub-lists."
:Evaluate: AddAll::badargs = "Arguments are expected to be positive numbers"
:Evaluate: AddAll::interr = "Internal error - error getting the data from Mathematica"
In[8]:= AddEight[{{1,2},{3,4}},{{5,6},{7,8}}]
Out[8]= {{6,8},{10,12}}
In[9]:= AddEight[{{-1,2},{3,4}},{{5,6},{7,8}}]
During evaluation of In[9]:= AddEight::badargs: Arguments are expected to be positive numbers
Out[9]= $Failed
In[10]:= AddAll[{{1,2},{3,4}},{{5,6},{7,8}}]
Out[10]= 36
In[11]:= AddAll[{{-1,2},{3,4}},{{5,6},{7,8}}]
During evaluation of In[11]:= AddAll::badargs: Arguments are expected to be positive numbers
Out[11]= $Failed
关于c++ - 数学 : MathLink error messages,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6526848/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!