用 aardio 我们可以简单地调用 C++ 代码
liebian365 2024-10-24 14:36 14 浏览 0 评论
我们今天就不说下面这种 aardio 调用原生 API 如何简单:
var point = { INT x; INT y; }
::User32.GetCursorPos(point);
我们今天要玩一点难度高一些的,例如玩 C++ 地看到头都打转的 COM 接口,我们今天说的 COM 接口,也不说那种写起来累人用起来很舒服的 COM 控件。
我们今天要说几个难度高一些的:
1、直接调用 VC++ 实现了 IDispatch 接口指针。
2、直接用 C++ 专有的 thiscall 约定调用 C++ 对象。
一般调用 COM 控件,我们知道要先注册 COM 控件,但是一般注册 COM 控件还是比较麻烦,大多数需要管理权限注册,出现恼人的警告对话框,体验不是很好。在 aardio 中一般可以免管理权限注册,甚至可以免注册调用很多 COM 控件。
但是仍然有一些 COM 控件比较顽固是不能免注册调用的,其实 COM 控件注册啊什么的搞得很复杂,最终只是为了创建一个 IDispatch 对象,如果我们可以跳过上面这些所有的步骤,这会是非常舒服的。
我们用 VC++ 创建 IDispatch 对象,然后直接拿到原生的 IDispatch 接口指针,并且直接转换为 aardio 对象,这带来的好处是:
1、不用再注册 COM 控件了。
2、当然也不用什么免注册了。
3、可以直接通过内存加载 DLL,不用再带一个 DLL 文件了。
今天我们用 VC6 来写一个简单的 DLL 做一下演示,别小看 VC6,VC6 是唯一所有操作系统都自带的系统 C++ 运行时,所以可以生成极小的 DLL,而且一般是够用的,当然你要换新版 VC++ ,写法一样。
先看 aardio 调用代码有多简洁:
import console;
//加载 DLL
var dll = raw.loadDll(#34;/test.disp.dll",,"cdecl");
//创建 COM 对象,aardio 可自动支持 IDispatch 接口
import com;
var comObject = com.QueryObjectR( dll.CreateIDispatchObjectP() );
//使用 COM 对象
comObject.name = "测试";
console.log( comObject.name );
console.pause();
是不是简洁到难以置信?!
要做到上面的效果,一个编程语言需要同时做到能支持原生 API 开发,还要能支持 COM 动态接口对象,能做到这 2 样的编程语言其实非常少。而真正做到简洁方便好用的就更少了。
下面我们再看一下上面这个 test.disp.dll 的 C++ 源代码,这个先要有心理准备,世界上最复杂的编程语言不是白叫的,如果学 aardio 这样简单的编程语言让我叫苦不迭,我很难保证你看到下面的 C++ 代码不会晕过去。
不过我已经尽力把下面的代码处理到尽可能简单了,你不需要安装巨无霸的 VC++ 开发环境,直接运行下面的代码就可以编译生成 DLL,aardio 自带 VC6 扩展库。
import vc6;
import console;
var vc = vc6( "/",, console.open() )
//输入 C++ 源码
vc.cpp = /******
#include <afxwin.h>
#include <afxdisp.h>
class CTestObject: public CCmdTarget
{
DECLARE_DYNCREATE(CTestObject)
CTestObject();
protected:
virtual ~CTestObject();
CString strName;
public:
afx_msg BSTR GetName();
afx_msg void SetName(LPCTSTR lpszName);
DECLARE_DISPATCH_MAP()
};
IMPLEMENT_DYNCREATE(CTestObject, CCmdTarget)
CTestObject::CTestObject() {
EnableAutomation();
AfxOleLockApp();
}
CTestObject::~CTestObject() {
AfxOleUnlockApp();
}
BEGIN_DISPATCH_MAP(CTestObject, CCmdTarget)
DISP_PROPERTY_EX(CTestObject, "version", GetName, SetName, VT_BSTR)
END_DISPATCH_MAP()
BSTR CTestObject::GetName()
{
return strName.AllocSysString();
}
void CTestObject::SetName(LPCTSTR lpszName)
{
strName = lpszName;
}
extern "C" __declspec(dllexport) LPDISPATCH __cdecl CreateIDispatchObject() {
LPDISPATCH pDispatch = ( new CTestObject() )->GetIDispatch(FALSE);//参数FALSE指定不要添加引用计数
return pDispatch;
}
******/
//编译生成DLL
vc.exec(
'cl *.cpp'
,'/W3' /*警告等级*/
,'/MD' /*使用多线程动态运行库*/
,'/O2 /Ot /EHsc' /*代码优化选项*/
,'/D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_AFXDLL" ' /*定义常数和宏*/
,'/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.disp.dll'/*输出文件名*/
,'/dll' /*输出DLL*/
,'/LIBPATH:".\LIB" /LIBPATH:".\LIB2"' /*指定库目录*/
)
好吧,我们进入下一个目标,使用 thiscall 协议调用 C++ 对象,现在你见过 C++ 代码了,我就不再把 C++ 代码,aardio 代码分开发了,用 C++ 编译 DLL,再用 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();
好吧,如果你只是想试着跑几句 C++ 代码,并不想生成 DLL,就像硬盘干干净净的,还能跑一下 VC++ 代码,aardio 提供了一个 vc6.loadcode() 函数可以直接运行 VC++ 代码,示例如下:
import vc6;
import console;
console.showLoading(" 正在加载 C++ 代码");
var dll = vc6.loadcode(`
#include <windows.h>
#include <winioctl.h>
extern "C" {
__declspec( dllexport ) int __cdecl getValue() {
return CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS);
}
}`);
var value = dll.getValue();
var str = string.format("0x%X",value);
console.log("已复制: " + str,value);
import win.clip;
win.clip.write(str);
console.pause();
相关推荐
- 快递查询教程,批量查询物流,一键管理快递
-
作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...
- 一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递
-
对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...
- 快递查询单号查询,怎么查物流到哪了
-
输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...
- 3分钟查询物流,教你一键批量查询全部物流信息
-
很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...
- 快递单号查询,一次性查询全部物流信息
-
现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...
- 快递查询工具,批量查询多个快递快递单号的物流状态、签收时间
-
最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...
- 快递查询软件,自动识别查询快递单号查询方法
-
当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...
- 教你怎样查询快递查询单号并保存物流信息
-
商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...
- 简单几步骤查询所有快递物流信息
-
在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...
- 物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号
-
最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...
- 连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息
-
快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...
- 快递查询教程,快递单号查询,筛选更新量为1的单号
-
最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...
- 掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析
-
在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...
- 从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息
-
在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...
- 物流单号查询,在哪里查询快递
-
如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)