各編程語言 + aardio 相互調用示例
代碼簡單、複製可用。aardio 快速調用 C,C++,C#,Java,R,V,Python,JavaScript,Node.js,Rust,PHP,Ruby,PowerShell,Fortran,Delphi,Julia,Nim,批處理 …… 演示。
aardio 直接調用系統 API 函數( 支持回調、相互調用 ):
var ret,point = ::User32.GetCursorPos({ int x; int y; })
aardio / JavaScript 相互調用( 支持 ES6 ):
import web.script; var vm = web.script("ES6") //導出 aardio 函數到 JavaScript vm.external = { log = function(...){ console.log(...) } } vm.script = /***** function TestFunction(a,b) { return a + b; } *****/ var ret = vm.script.TestFunction(2,3);
在 aardio 中調用 Python( Python 調用 aardio 同樣簡單,參考 aardio 自帶範例),簡單得就像在 Python 中使用 Python:
import console; import py3; //導入 Python 模塊。 var itertools = py3.import("itertools") //調用 Python 函數,支持純 aardio 類型參數 var permutations = itertools.permutations({"a","b","c"}); //調用 Python 內置函數 list var pyList = py3.list(permutations); //遍歷 Python 對象成員 for( item in pyList.each() ){ console.log(item); //像 aardio 對象一樣使用 Python 對象 } console.pause();
aardio 直接調用 .Net / C# 組件( 支持相互調用,支持委託這些)
import win.ui; var winform = win.form(text="DataGridView") import System.Data; var tab = System.Data.DataTable("DT"); tab.Columns.Add("名稱"); tab.Rows.Add({"WangWu"}); import System.Windows.Forms; var grid = System.Windows.Forms.CreateEmbed("DataGridView",winform); grid.ColumnHeadersHeightSizeMode = 2; grid.DataSource = System.Data.DataView(tab); winform.show(); win.loopMessage();
aardio 直接調用 Java ( 也支持相互調用 )
import java; var jvm = java(); //加載Java類對象 HelloworldApp = jvm.import("aardio.sample.HelloworldApp"); //也可以如下自內存或文件直接加載類, HelloworldApp = jvm.import("aardio.sample.HelloworldApp",$"\java\aardio\sample\HelloworldApp.class"); //用 Java 類創建 Java 對象 var helloworld = HelloworldApp(); //直接調用 Java 對象的方法 var result = helloworld.test(3);
用 aardio 編譯 C 語言代碼生成 DLL 執行文件,再調用 DLL 中的 C 函數:
import tcc; //編譯 DLL tcc.build( "/start.dll" ).code = /*** #include <windows.h> __declspec(dllexport) int Add( int a,int b ) { return a + b; } ***/ //加載 DLL var dll = raw.loadDll( "/start.dll",,"cdecl" ); //調用 C函數 var result = dll.Add(12,3);
在 aardio 中嵌入並調用批處理:
import console import process.batch; //批處理 for 遍歷並拆分字符串 var bat = process.batch(` @echo off for %%i in (abc,def,xyz) do echo %%i `) console.log(bat.read(-1)) console.pause()
aardio 調用 Rust 語言解析 TOML:
import console; import string.toml; var str = string.toml.stringify({abc=123,d={1,2,3}}); console.log( str ); import process.code; process.code("~\lib\string\toml\.res"); console.pause(true);
在 aardio 里嵌入 PHP,以下短短几句代碼,包含了 HTTP 服務器,PHP服務端,嵌入的瀏覽器組件:
import win.ui; /*DSG{{*/ var winform = win.form(text="Hello World / PHP_CGI 服務器") /*}}*/ var code = /* <html> <head> <meta charset="utf-8"> <title>PHP 測試</title> </head> <body> <?php echo '<p>Hello World / PHP_CGI 服務器</p>'; ?> </body> </html> */ string.save("/test.php",code); import php.simpleHttpServer; var url = php.simpleHttpServer.startUrl("/test.php"); import web.form; var wb = web.form(winform); wb.go(url); winform.show(); win.loopMessage();
aardio 調用 PowerShell,並且在 PowerShell 中調用 aardio。這甚至都不用帶上體積較大的
System.Management.Automation.dll,一個輕巧的 EXE 就可以搞定一切,向下兼容到 PowerShell 2.0 :
import dotNet.ps; var pScript = /* # 聲明 PowerShell 參數 param($win) # 修改 aardio 對象屬性 $win.title = "PowerShell + aardio"; # 調用 aardio 對象函數 $win.msgbox("這是 PowerShell 調用 aardio 打開的對話框。") */ import win; dotNet.ps(pScript,{ win = win; //# 將 aardio 對象作為參數傳給 PowerShell });
aardio 執行 Ruby 語言代碼 :
import win.ui; /*DSG{{*/ var winform = win.form(text="執行Ruby代碼") winform.add( edit={cls="edit";left=26;top=16;right=737;bottom=435;multiline=1;z=1} ) /*}}*/ import process.ruby; var out = process.ruby.exec("puts '測試UTF-8'") winform.edit.print(out); var out = process.ruby.eval(`[1, 2, { name: "tanaka", age: 19 }]`) winform.edit.print(out); winform.show(); win.loopMessage();
aardio 調用 Node.js :
import console; import nodeJs; var js = /****** console.log(process.argv); var startEnviron = require('startEnviron'); console.log(startEnviron.dest); ******/ //自動分析 JS 代碼中的 require 語句並安裝依賴模塊 nodeJs.requireByJs(js); //把對象傳給 node.js,在 JS 代碼中用 require('startEnviron') 獲取。 nodeJs.startEnviron({ src:"傳個字符串",dest:{test:"嵌套的對象表,傳給node.js都沒問題",number:123, arr:{1,2,3} } }) //執行JS,這裡指定的啟動參數在 JS 代碼中可用 process.argv 獲取。 var prcs = nodeJs.exec(js,"--args1=1","--args2=1"); prcs.logResponse(); console.pause(true);
aardio 調用 Fortran ( DLL 源碼在 aardio 範例里有 ) :
import console //加載 DLL , DLL 路徑前加 $ 實現內存加載 DLL(發佈後不需要外部 DLL 文件) var dll = raw.loadDll($"/fortran.dll",,"cdecl"); //不聲明直接調用,結構體默認傳址,這不用改什麼。 var c = dll.__test_MOD_addbypoint({ int x = 22; int y = 3; }) console.log(c); //可以先聲明一下,參數類型加上&聲明為按引用傳址(指針) var add = dll.api("__test_MOD_add","int(int &a,int &b)") var c = add(33,2); //Fortran 的數值參數默認都是傳址(傳指針) //不聲明直接調用可以用結構體取代指針 var c = dll.__test_MOD_add({int a=33},{int b=2}); //用 raw.int 創建傳址數值也可以 var c = dll.__test_MOD_add(raw.int(33,true),raw.int(2,true)); //參數聲明為傳值時調用更簡單,不聲明調用時數值默認為 int 類型 var c = dll.__test_MOD_addbyval(33,2,raw.double(123)); console.log(c); //字符串 var str = "hello"; //只讀字符串,改用 raw.buffer 創建可讀寫位元組數組 dll.__test_MOD_hello(str,#str); //注意到字符串長度傳過去 console.pause(true);
aardio 調用 C++ :
import vc6; import console; console.open(); var vc = vc6( "/" ) //輸入C++源碼 vc.cpp = /****** #include <windows.h> struct TestInfo{ int x; int y; BYTE name[256]; }; class CTestObject { public: //注意函數聲明前加上 virtual 以支持 aardio 中的 raw.interface virtual void getName(char *buffer,int len); virtual void getInfo(TestInfo *pInfo); }; void CTestObject::getName(char *buffer,int len){ strcpy(buffer,"測試"); } void CTestObject::getInfo(TestInfo *pInfo){ pInfo->x = 1; pInfo->y = 2; strcpy((char *)pInfo->name,"測試"); } extern "C" __declspec(dllexport) CTestObject* __cdecl CreateTestObject() { return new CTestObject(); } extern "C" __declspec(dllexport) void __cdecl DeleteTestObject( CTestObject* pTest) { delete pTest; } ******/ //編譯生成DLL vc.exec( 'cl *.cpp' ,'/W3' /*警告等級*/ ,'/MD' /*使用多線程動態運行庫*/ ,'/O2 /Ot /EHsc' /*代碼優化選項*/ ,'/D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL"' /*定義常數和宏*/ ,'/I"./INCLUDE"'/*指定頭文件目錄*/ ,'kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib' /*導入庫*/ ,'/link /SUBSYSTEM:WINDOWS /MACHINE:X86' /*後面是鏈接參數 */ ,'/out:test.dll'/*輸出文件名*/ ,'/dll' /*輸出DLL*/ ,'/LIBPATH:".\LIB" /LIBPATH:".\LIB2"' /*指定庫目錄*/ ) var dll = raw.loadDll("/test.dll",,"cdecl"); import raw.interface; class testObject{ ctor(){ //創建 C++ 對象,並獲取指針,注意這裡使用了 P 尾標獲取指針。 var pTest = dll.CreateTestObjectP(); //C++ 對象指針轉換為 aardio 對象。 this = ..raw.interface( pTest," void getName(string &buffer,int len); void getInfo(struct &pInfo); ","thiscall" //注意調用約定為thiscall ) //添加析構函數 ..table.gc(this,"delete") }; delete = function(){ if(!owner.deleted){ dll.DeleteTestObject( owner ); owner.deleted = true; } }; } //創建對象 var obj = testObject(); //調用 C++ 函數 var name = obj.getName(25,25); console.log(name); //調用 C++ 函數 var info = obj.getInfo({ int x;int y;BYTE name[256]}) console.log( info.name ); console.pause();
aardio 調用 FreeBASIC ( DLL 源碼在 aardio 範例里有 ) :
//加載DLL,DLL路徑前面加上$表示把DLL嵌入到程序中並通過內存加載 var dll = raw.loadDll( $"\basic.dll",,"cdecl" //注意參數里指定使用 cdecl 調用約定。 ); //定義結構體,當然也可以先聲明一個 class 來創建實例。 var info = { int x; INT y; } // 然後直接調用 API var ret = dll.msgboxW(123,456,"測試一下好用不好用",info); //最後打印結構體看一下值 import console; console.log(ret); console.dumpJson(info); console.pause(); aardio 調用 Delphi ( DLL 源碼在 aardio 範例里有) : import win.ui; //內存加載 DLL var delphiDll = raw.loadDll($"\Project1.dll"); class win.ui.ctrl.delphiForm{ ctor(parent,tParam){ this.hwnd = delphiDll.CreateForm(parent.hwnd); }; @..win.ui.ctrl.metaProperty() } /*DSG{{*/ var winform = win.form(text="用 Delphi 語言為 aardio 編寫控件";right=507;bottom=423;bgcolor=11842740) winform.add( custom={cls="delphiForm";text="嵌入 Delphi 控件";left=17;top=28;right=490;bottom=211;db=1;dl=1;dr=1;dt=1;z=1}; edit={cls="edit";text="請先用 Delphi 打開此目錄下的 DLL 源碼工程編譯生成 \Project1.dll";left=16;top=228;right=489;bottom=398;edge=1;multiline=1;z=2} ) /*}}*/ import web.json; winform.onTest = function(delphiStructParam){ winform.edit.print("Delphi 調用了aardio 函數,參數如下:"); winform.edit.print(delphiStructParam); delphiStructParam.x = 90; //可選返回修改後的結構體 return delphiStructParam; } winform.edit.text = ""; winform.show(); win.loopMessage();
aardio 調用 R 語言:
import console; import process.r; //執行 R 代碼,支持 aardio 模板語法 process.r.code = /* write("<?="這是 aardio 代碼"?>",file=".data.txt"); */ //執行 R 代碼,支持 aardio 模板語法 var out = process.r.loadcode(`write("<?="這是 aardio 代碼"?>",file=".data.txt");`) //執行純 R 代碼,參數 @1 可以指定 R代碼或 R 文件。 var out = process.r.exec(` args=commandArgs(T); write(args[1],file=".data.txt"); # list 有點像 aardio 中的表(table),可以包含各種數據類型, a <- list(hello = 1, world = "字符串" ) # <- 相當於 aardio 中的等號, R的等號一般用於分隔鍵值對 print ( a[["world"]] ); # aardio 里的直接下標也是這麼寫 print ( a$world ); # 相當於 aardio 里的 a.world print ( a[1] ); # 這個返回的是鍵值對 hello = 1,不像 aadio 中 a[1] 與 a.hello 是指向不同的元素。 print ( mode(a[1]) ); # 數據類型還是顯示為 list b <- TRUE #布爾值必須全大寫 print( b ) # 向量 a = c(10, 20, 30, 40, 50) print( a[1] ) #起始下標為 1 ,這跟 aardio 一樣 print( a[1:4] ) # 取出第 1 項到第 4 項 # 定義函數,與 aardio 語法類似 new.function <- function(a,b,c) { result <- a * b + c # 類似 aardio 中的 return a * b + c # print(result) # 指定返回值以後,還能繼續執行後面的代碼,不像 aardio 函數 return 後面的代碼被忽略。 } print( new.function(2,3,1) ) `,"測試一下"); //可以添加不定個數的啟動參數 console.log( out ); console.more(,true); console.showLoading(" 正在安裝 rjson 包"); process.r.require("rjson","//mirrors.ustc.edu.cn/CRAN/");//不會重複安裝 var out = process.r.exec( ` library("rjson") # 載入 rjson 包 args <- commandArgs(T); tab <- fromJSON(args[1], simplify=FALSE); #不要用 print ,cat 不會加一堆不必要的東西 cat( toJSON(tab) ) `, { name1 = "測試一下,傳對象給 R 語言"; name2 = "這是一個 aardio 對象" }) console.dump(out); var rCode = /* testabc <- function(a,b,c) { result <- a * b + c # 類似 aardio 中的 return a * b + c # print(result) # 指定返回值以後,還能繼續執行後面的代碼,不像 aardio 函數 return 後面的代碼被忽略。 } */ //啟動 R var r = process.r.startRpc(rCode); //調用 R 函數 var ret = r.testabc(2,3,1) //打印 R 函數返回值 if(ret[["result"]]){ console.log("R 函數返回值",ret[["result"]]) } console.pause(true);
aardio 調用 Julia :
import console; import julia; //調用 Julia 函數 var ret = julia.sqrt(2); console.log(ret); //導入 Julia 模塊 julia.using("Base64"); var data = julia.Base64.base64encode("測試一下"); console.log( data ); //轉換 Julia 數據類型 var buf = julia.value.build(raw.buffer("abc")); console.log(julia.typeof(buf)); //執行 Julia 代碼並獲取返回值 var refs = julia.eval("refs = IdDict("); //查看 Julia 代碼錯誤 console.log(julia.lasterr()); console.pause();
aardio 調用 Nim 語言:
import console; var nimCode = /* {.pragma: rtl, exportc, dynlib, cdecl.} import md5 # Nim 雙引號中的字符串,相當於 aardio 中用單引號包含的轉義字符串 # aardio 中雙引號包含的字符串,相當於 Nim 中的原始字符串: r"原始字符串" # Nim 與 aardio 都是 UTF-8 編碼,aardio 的文本字符串在 Nim 中的類型為 cstring # Nim 中 string 可以隱式轉換為 cstring, cstring 加上 $ 轉為 string 類型 proc build*(str: cstring, num: ptr[cint]): cstring {.rtl.} = num[] = num[] * 2 result = md5.getMD5($str) */ string.save("/test.nim",nimCode ) import process.nim; process.nim("c --app:lib -d:release -r test.nim") //支持改為 $"/test.dll" 內存加載 DLL, //但這時候 test.dll 還未生成,所以示例里沒有加 $ //用cdecl 調用約定的好處是:導出函數名直接可用,不會被加上修飾名 var test = raw.loadDll("/test.dll",,"cdecl") //nim 與 aardio 的字符串都是 UTF-8 編碼,UTF-8 真是到處通行,非常方便省了很多事 var build = test.api("build","str(str,int& num)" ) //一般C語言不能這麼直接返回字符串(要考慮誰釋放內存)。 //但是 nim 可以投機取巧一下,nim 會自動回收內存,而這時候還來不及回收。 var str,num = build("測試abc",9) console.log(str,num) //用 aardio 算出 MD5 對比一下,結果一模一樣 import crypt; console.log(crypt.md5("測試abc",false)) console.pause();
aardio 調用 V 語言:
import console; import process.v; console.open(); //V語言不支持中文路徑,所以工程目錄路徑不要包含任何中文 string.save("/hello.v"," struct Point { pub mut: //聲明下面的字段公開、可變 x int y int } [export: 'add'] //一定要用這句指定DLL導出函數名 pub fn add(a int,b int,mut pt &Point) int { pt.x = a+b return a+b }" ) /* V語言是翻譯成C語言然後生成DLL,生成的DLL依賴 VC 運行庫, 試了換成調用TCC編譯,10KB的DLL增大到 400KB,並且運行崩潰。 */ process.v.shared("hello.v").waitOne(); //V生成的DLL建議至少在 WIN10 上用,需要VC++2017運行庫 import sys.vc14; sys.vc14.require(); //檢測並自動安裝 VC++ 運行庫 //導入DLL,注意要指定 cdecl 調用約定 var dll = raw.loadDll("/hello.dll",,"cdecl") //調用 V 函數( V是翻譯為C語言,所以參考C語言的規則) var n,pt = dll.add(12,3,{int x=1;int y =2}); //輸出結果 console.log(n); console.dumpJson(pt); console.pause(true);