RGSS 扩展编写指南

选择本文使用的编译器: ,本文平台:Windows 10

Dll 入门

int __stdcall add(int a, int b) { return a + b; }

编写 .def 文件

EXPORTS
    add

编译

cl /LD a.c /link /def:a.def
clang -m32 -shared a.c -o a.dll -Wl,-def:a.def
gcc -m32 -shared a.c -o a.dll

调用

Win32API.new('a.dll', 'add', 'll', 'l').call(3, 5) #=> 8

Win32API 入门

导入导出参数类型只能使用 VPpNnLlIi,调用约定使用 stdcall,系统函数四字节对齐

举例:MessageBox

int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
MessageBox = Win32API.new('user32', 'MessageBox', 'LppL', 'L')
MessageBox.call(0, 'content', 'title', 16)

举例:GetCursorPos

BOOL GetCursorPos(LPPOINT lpPoint);
GetCursorPos = Win32API.new('user32', 'GetCursorPos', 'p', 'L')
GetCursorPos.call(doubleL = "\0" * 8)
point = doubleL.unpack('LL') #=> [12, 34]

常用方法

# 移除末尾空格和 "\0"
"asd \0\0\0".unpack('A*') #=> "asd"
# 移除末尾 "\0"
"asd \0\0\0".unpack('Z*') #=> "asd "
# 添加 "\0";注意,使用 WideChar 时可能要添加两个 "\0"
["asd"].pack('Z*') #=> "asd\0"
["asd\0"].pack('Z*') #=> "asd\0\0"
# ASCII 范围内的 UTF-8/WideChar 互换
'hello'.unpack('U*').pack('S*') #=> "h\0e\0l\0l\0o\0"
"h\0e\0l\0l\0o\0".unpack('S*').pack('U*') #=> 'hello'
# 强行使用二进制编码(防止 UTF-8 编码报错)
"hello".b

机器码入门

gcc -w -m32 -c -O -fno-ident a.c
objcopy -O binary -j .text a.o a
8b44 2408 0344 2404 c3 
objdump -M intel -S a.o
00000000 <_Add>:
   0:   8b 44 24 08             mov    eax,DWORD PTR [esp+0x8]
   4:   03 44 24 04             add    eax,DWORD PTR [esp+0x4]
   8:   c3                      ret
CallWindowProc = Win32API.new 'user32', 'CallWindowProc', 'pLLLL', 'L'
CallWindowProc.call [
	0x8b, 0104,0044, 8,  # [1] mov 8(%esp), %eax
	0x03, 0104,0044, 4,  # [0] add 4(%esp), %eax
	0xc2,         16,0,  #     ret $16
].pack('C*'), 3, 5, 0, 0 # => 8

进阶:传递函数参数

int compare_ints(const void* a, const void* b) {
	int arg1 = *(const int*)a;
	int arg2 = *(const int*)b;

	if (arg1 < arg2) return -1;
	if (arg1 > arg2) return 1;
	return 0;
}

int ints[] = { -2, 99, 0, -743, 2, INT_MIN, 4 };
int size = sizeof ints / sizeof *ints;

qsort(ints, size, sizeof(int), compare_ints);

等价 Ruby 写法

compare_ints = [
	%w[ 8b44 2404 8b10 8b44 2408 8b00 39c2 7c07
		0f9f c00f b6c0 c3b8 ffff ffff c390 9090 ].join
].pack('H*')

ints = [ -2, 99, 0, -743, 2, -2147483648, 4 ].pack('l*')
size = 7

dll('msvcrt').qsort(ints, size, 4, compare_ints)
ints.unpack('l*')
#=> [-2147483648, -743, -2, 0, 2, 4, 99]

进阶:异步函数

AsHttp 为例,导出诸如 GetState 等同步函数,对应 RGSS 脚本

其他例子:

© 2019 hyrious