Skip to content

Commit

Permalink
Work in progress Qt interface
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@24163 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Jan 23, 2015
1 parent 8cd3650 commit 5216c43
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Compiler/FrontEnd/ModelicaBuiltin.mo
Expand Up @@ -3174,7 +3174,8 @@ loadString(\"model DoublePendulum
extends Modelica.Mechanics.MultiBody.Examples.Elementary.DoublePendulum;
inner ModelicaServices.Modelica3D.Controller m3d_control;
end DoublePendulum;\");getErrorString();
simulate(DoublePendulum);</pre>
system(\"python \" + getInstallationDirectoryPath() + \"/lib/omlibrary-modelica3d/osg-gtk/dbus-server.py &amp;\");getErrorString();
simulate(DoublePendulum);getErrorString();</pre>
<p>This API call will load the modified ModelicaServices 3.2.1 so Modelica3D runs. You can also simply call loadModel(ModelicaServices,{\"3.2.1 modelica3d\"});</p>
<p>You will also need to start an m3d backend to render the results. We hid them in $OPENMODELICAHOME/lib/omlibrary-modelica3d/osg-gtk/dbus-server.py (or blender2.59).</p>
<p>For more information and example models, visit the <a href=\"https://mlcontrol.uebb.tu-berlin.de/redmine/projects/modelica3d-public/wiki\">Modelica3D wiki</a>.</p>
Expand Down
5 changes: 3 additions & 2 deletions Compiler/Script/CevalScript.mo
Expand Up @@ -882,7 +882,7 @@ public function cevalInteractiveFunctions2
algorithm
(outCache,outValue,outInteractiveSymbolTable) := matchcontinue (inCache,inEnv,inFunctionName,inVals,inSt,msg)
local
String omdev,simflags,s1,str,str1,str2,str3,token,varid,cmd,executable,executable1,encoding,method_str,
String omdev,simflags,s1,s2,str,str1,str2,str3,token,varid,cmd,executable,executable1,encoding,method_str,
outputFormat_str,initfilename,cit,pd,executableSuffixedExe,sim_call,result_file,filename_1,filename,
call,str_1,mp,pathstr,name,cname,errMsg,errorStr,
title,xLabel,yLabel,filename2,varNameStr,xml_filename,xml_contents,visvar_str,pwd,omhome,omlib,omcpath,os,
Expand Down Expand Up @@ -2189,7 +2189,8 @@ algorithm
end matchcontinue;
end for;
s1 := Tpl.tplString(GenerateAPIFunctionsTpl.getCevalScriptInterface, tys);
then (cache,Values.TUPLE({Values.BOOL(true),Values.STRING(s1),Values.STRING("")}),st);
s2 := Tpl.tplString2(GenerateAPIFunctionsTpl.getQtInterface, tys, "OMCProxy");
then (cache,Values.TUPLE({Values.BOOL(true),Values.STRING(s1),Values.STRING(s2)}),st);

case (cache,env,"generateScriptingAPI",{Values.CODE(Absyn.C_TYPENAME(className))},st as GlobalScript.SYMBOLTABLE(ast = p),_)
then (cache,Values.TUPLE({Values.BOOL(false),Values.STRING(""),Values.STRING("")}),st);
Expand Down
132 changes: 132 additions & 0 deletions Compiler/Template/GenerateAPIFunctionsTpl.tpl
Expand Up @@ -115,6 +115,138 @@ template getCevalScriptInterfaceFunc(String name, list<DAE.FuncArg> args, DAE.Ty
>>
end getCevalScriptInterfaceFunc;

template getQtInterface(list<DAE.Type> tys, String className)
::=
let heads = tys |> ty as T_FUNCTION(source=path::_) => '<%getQtInterfaceHeader(pathLastIdent(path), "", ty.funcArg, ty.funcResultType, className)%><%\n%>'
let funcs = tys |> ty as T_FUNCTION(source=path::_) => '<%getQtInterfaceFunc(pathLastIdent(path), ty.funcArg, ty.funcResultType, className)%><%\n%>'
<<
#include <Qt/QtCore>
#include "OpenModelicaScriptingAPI.h"

<%funcs%>
>>
end getQtInterface;

template getQtType(DAE.Type ty)
::=
match ty
case T_STRING(__) then "QString"
case T_INTEGER(__) then "modelica_integer"
case T_BOOL(__) then "modelica_boolean"
case T_REAL(__) then "modelica_real"
case aty as T_ARRAY(__) then 'QList<<%getQtType(aty.ty)%>>'
case T_CODE(ty=C_TYPENAME(__)) then "QString"
else error(sourceInfo(), 'getQtType failed for <%unparseType(ty)%>')
end getQtType;

template getQtInterfaceHeader(String name, String prefix, list<DAE.FuncArg> args, DAE.Type res, String className)
::=
let inTypes = args |> arg as FUNCARG(__) => '<%getQtType(arg.ty)%> <%arg.name%>' ; separator=", "
let outType = match res
case T_TUPLE(__) then
<<
typedef struct {
<%types |> ty hasindex i fromindex 1 => '<%getQtType(ty)%> res<%i%>;' ; separator="\n" %>
} <%name%>_res;
<%name%>_res
>>
case T_NORETCALL(__) then "void"
else '<%getQtType(res)%>'
<<
<%outType%> <%prefix%><%name%>(<%inTypes%>)
>>
end getQtInterfaceHeader;

template getQtInArg(Text name, DAE.Type ty, Text &varDecl)
::=
match ty
case T_CODE(ty=C_TYPENAME(__))
case T_STRING(__) then
let &varDecl += 'QByteArray <%name%>_utf8 = <%name%>.toUtf8();<%\n%>'
'mmc_mk_scon(<%name%>_utf8.data())'
case T_INTEGER(__)
case T_BOOL(__)
case T_REAL(__) then name
case aty as T_ARRAY(__) then
let &varDecl2 = buffer ""
let elt = '<%name%>_elt'
let body = getQtInArg(elt, aty.ty, varDecl2)
let &varDecl +=
<<
void *<%name%>_lst = mmc_mk_nil();
for (int <%name%>_i = <%name%>.size()-1; i>=0; i--) {
<%getQtType(aty.ty)%> <%elt%> = <%name%>[<%name%>_i];
<%varDecl2%>
<%name%>_lst = mmc_mk_cons(<%body%>, <%name%>_lst);
}<%\n%>
>>
'<%name%>_lst'
else error(sourceInfo(), 'getQtInArg failed for <%unparseType(ty)%>')
end getQtInArg;

template getQtOutArg(Text name, Text shortName, DAE.Type ty, Text &varDecl, Text &postCall)
::=
match ty
case T_CODE(ty=C_TYPENAME(__))
case T_STRING(__) then
let &varDecl += 'void *<%shortName%>_mm = NULL;<%\n%>'
let &postCall += '<%name%> = QString::fromUtf8(MMC_STRINGDATA(<%shortName%>_mm));<%\n%>'
'&<%name%>_mm'
case T_INTEGER(__)
case T_BOOL(__)
case T_REAL(__) then '&<%name%>'
case aty as T_ARRAY(__) then
let &varDecl += 'void *<%shortName%>_mm = NULL;<%\n%>'
let &varDecl2 = buffer ""
let &postCall +=
<<
while (!listEmpty(<%shortName%>_mm)) {
<%varDecl2%>
<%getQtType(aty.ty)%> <%shortName%>_elt = MMC_CAR(<%shortName%>_mm);
<%name%>.push_back(...);
<%shortName%>_mm = MMC_CDR(<%shortName%>_mm);
}<%\n%>
>>
'&<%name%>_mm'
else error(sourceInfo(), 'getQtOutArg failed for <%unparseType(ty)%>')
end getQtOutArg;

template getQtInterfaceFunc(String name, list<DAE.FuncArg> args, DAE.Type res, String className)
::=
let &varDecl = buffer ""
let &postCall = buffer ""
let inArgs = args |> arg as FUNCARG(__) => ', <%getQtInArg(arg.name, arg.ty, varDecl)%>'
let outArgs = (match res
case T_NORETCALL(__) then ""
case t as T_TUPLE(__) then
let &varDecl += '<%name%>_res result;<%\n%>'
(types |> t hasindex i1 fromindex 1 => ', <%getQtOutArg('result.res<%i1%>', 'out<%i1%>', t, varDecl, postCall)%>')
else
let &varDecl += '<%getQtType(res)%> result;<%\n%>'
', <%getQtOutArg('result', 'result', res, varDecl, postCall)%>'
)
<<
<%getQtInterfaceHeader(name, '<%className%>::', args, res, className)%>
{
<%varDecl%>
MMC_TRY_TOP_INTERNAL()
st = omc_OpenModelicaScriptingAPI_<%name%>(threadData, st<%inArgs%><%outArgs%>);
<%postCall%>
MMC_CATCH_TOP(throw std::runtime_error("getClassInformation failed");)
/*
while (!MMC_NILTEST(dimensions)) {
result.dimensions.push_back(MMC_STRINGDATA(MMC_CAR(dimensions)));
dimensions = MMC_CDR(dimensions);
}
*/
}
>>
end getQtInterfaceFunc;

annotation(__OpenModelica_Interface="backend");
end GenerateAPIFunctionsTpl;

Expand Down

0 comments on commit 5216c43

Please sign in to comment.