- 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/
我尝试将 python 2.x 代码移植到 python 3。我正在努力解决的问题是 from mimetools import Message ... headers = Message(Strin
我有一个输入组件,它有三种类型的验证(required、validatorMessage、converterMessage),这个输入有自己的消息图标,整个表单有一个消息组件来显示所有组件的所有消息,
我有一个使用消息代理 (activemq) 的带有 spring 和 websockets 的 webapp。 这是我的配置类: @Configuration @EnableWebSocketMess
据我了解mbox Python 3.6 标准库中的类生成 email.message.Message 类型的旧式消息对象. 较新的类(class) email.message.EmailMessage
我使用的是mysql。 我有一个包含 userid、message_id、opened(true 或 false)、时间戳的消息表。 我希望所有未打开最近收到的 5 条消息的用户 这就是我现在拥有的:
我是 Android 的新手,发现要不断更新主视图,我必须创建一个线程来处理各种进程,然后将更新传回主视图。我决定使用 Handler 类来执行此操作。此示例中的 View 有一个用于激活代码的按钮和
我遇到了重定向符号的不同位置( > , &2 message message echo message >&2 message >&2 echo message message 对于所有表单,我得到了
我想使用 firebase 云函数发送通知,所以我尝试使用 firebase.messaging().getToken() 获取 token ,但我不断收到错误消息: TypeError: fireb
我实现了一个短信应用。现在我在使用 Oppo 设备时遇到了问题,因为无论何时收到消息,系统都会将默认应用程序更改为内置应用程序并显示此消息: For your messages security, S
我正在实现本指南:https://spring.io/guides/gs/centralized-configuration/关于Spring Cloud配置。 服务器: @EnableConfigS
我想在“匹配”之后,向所有比赛发送介绍信息。你知道一种轻松发送的方法吗?(我使用 Bluestacks) 提前致谢。问候。 最佳答案 只需传递 session.send()在session.dialo
在我们的应用程序中,我们使用 kafka 并有一个像这样的 Spring Cloud 输入流 @Component public interface SomeChannel { @Input(
这周我在通过 Node.js 库(代码相同,库版本相同等)向我的 iOS 设备发送消息时遇到了很多内部错误 很难调试,因为有时它会起作用。当我使用 for 循环发送 10 条消息时,我的设备将收到 3
我目前正在记录错误并希望获得尽可能多的描述性细节。我知道我可以捕获许多不同类型的异常,但 Exception.Message 之间有什么区别?和 Exception.InnerException.Me
我创建了一个映射到 MyBean.beansField 的表单。我使用 javax.validation.NotNull 注释来确保必须输入它。到目前为止一切正常,但错误消息如下所示: beansFi
我正在研究 Azure 服务总线。我的服务总线队列正在处理一条消息 3 次。我的消息锁定时间是5分钟。每条消息最多处理 2 分钟,但我不知道为什么队列会选择相同的消息并发送到处理,而重复的消息仅在 5
我正在使用最新的快速修复版本,即 1.6.0。我已经有针对 1.5.3 编写的代码,我想做的是将其升级到 1.6.0 我遇到的问题是,当我使用破解(msg,sessionID)方法时,它会抛出quic
当我调用 grails message()函数来查找和评估消息 key 对,它无法评估参数。 在我的 Controller 中,我调用消息函数: rejectWithError(message(cod
我使用一个小型 Spring 应用程序,其中数据库中的值很少,我想使用可变调用来检索它们。 API 在这里, @RestController @RequestMapping("/api/v1/prod
我在想在用以更好的方式,像这样: Please inform us about: 这个想法是以一种不同的方式向用户展示消息,具有更多的风格。这可能吗? 最佳答案 它们可通过 Fac
我是一名优秀的程序员,十分优秀!