Bridge RPC – Nền tảng tích hợp DLL đa ngôn ngữ, không phụ thuộc 32-bit hay 64-bit (1 người xem)

Người dùng đang xem chủ đề này

Tôi tuân thủ nội quy khi đăng bài

phuongnam366377

Thành viên thường trực
Tham gia
25/10/19
Bài viết
274
Được thích
242
Ý tưởng từ chủ đề sau

cũng không ngờ nhờ có AI viết ra hệ thống này từ ý tưởng của Thetrik

Keo ChatGPT viết bài sau ...

Bridge RPC – Nền tảng tích hợp DLL đa ngôn ngữ, không phụ thuộc 32-bit hay 64-bit​

Giới thiệu​

Trong toàn bộ kiến trúc Bridge RPC, thành phần quan trọng nhất là BridgeInvoker64.dll.

Thư viện này được phát triển bằng C++ Builder và hoạt động như một Dynamic Win64 ABI Invocation Engine.

Nói đơn giản, đây là lớp trung gian cho phép gọi các hàm native của DLL tại thời điểm chạy mà không cần biết trước chữ ký hàm khi biên dịch.

Trong quá trình phát triển phần mềm, đặc biệt với các ứng dụng VBA, VB6, Delphi, C++ hay Go, một trong những khó khăn thường gặp là việc tích hợp các thư viện DLL được biên dịch bởi các ngôn ngữ và kiến trúc khác nhau.

Ví dụ:

  • VBA 32-bit không thể gọi trực tiếp DLL 64-bit.
  • VB6 chỉ chạy 32-bit.
  • Go chỉ hỗ trợ biên dịch DLL 64-bit trên Windows hiện đại.
  • Mỗi ngôn ngữ lại có ABI và cơ chế gọi hàm khác nhau.
Thông thường các giải pháp phổ biến là:

  • COM/DCOM
  • .NET Interop
  • REST API
  • gRPC
Tuy nhiên các giải pháp này thường khá nặng hoặc phức tạp đối với những ứng dụng desktop nhỏ và vừa.

Từ nhu cầu thực tế đó, tôi xây dựng một nền tảng trung gian có tên là Bridge RPC.


Ý tưởng​

Thay vì để ứng dụng gọi trực tiếp DLL đích, mọi lời gọi sẽ đi qua một lớp RPC trung gian.

Kiến trúc tổng quát:

Client Application
(VBA / VB6 / Delphi / Go / C++)



BridgeClient.dll



TCP RPC



BridgeServer.exe



BridgeInvoker64.dll



Business DLL

Nhờ kiến trúc này:

  • Client không cần biết DLL được viết bằng ngôn ngữ nào.
  • Client không cần biết DLL đang chạy 32-bit hay 64-bit.
  • DLL nghiệp vụ có thể được thay đổi hoặc mở rộng mà không ảnh hưởng phía ứng dụng.

Điểm đặc biệt​

Bridge RPC không ràng buộc vào một ngôn ngữ cụ thể.

Hiện tại tôi đã thử nghiệm thành công với:

  • VBA 32-bit
  • VBA 64-bit
  • VB6
  • Delphi
  • C++ Builder
  • Go
Tất cả đều sử dụng cùng một giao thức.

Phía client chỉ cần gửi:

  • Tên hàm
  • Danh sách tham số
  • Kiểu dữ liệu
Phần còn lại được xử lý tự động.


Dynamic ABI Invocation​

Thành phần quan trọng nhất của hệ thống là BridgeInvoker64.dll.

Nó hoạt động như một Dynamic ABI Invocation Engine.

Thay vì phải biết trước chữ ký hàm:

int Add(int A, int B);<br>
BridgeInvoker64.dll nhận mô tả tham số tại thời điểm chạy:

Function Pointer<br>+<br>Argument Metadata<br>+<br>Return Type<br>
sau đó tự động:

  • Phân bổ thanh ghi
  • Sắp xếp stack
  • Thực hiện lời gọi theo Microsoft x64 ABI
  • Thu nhận giá trị trả về
Điều này cho phép gọi nhiều hàm khác nhau mà không cần viết wrapper riêng cho từng hàm.


Hỗ trợ kiểu dữ liệu​

Hệ thống hiện hỗ trợ:

  • Int32
  • UInt32
  • Int64
  • UInt64
  • Double
  • Pointer
Hỗ trợ tối đa 16 tham số cho mỗi lời gọi hàm.


Một ví dụ đơn giản​

Từ VBA:

Dim Json As String<br><br>Json = BridgeQueryJSON( _<br> "SELECT * FROM [NhapXuatTon]")<br>
Phía VBA hoàn toàn không cần biết:

  • DLL được viết bằng Delphi hay Go
  • Hàm thực thi nằm ở đâu
  • Đang chạy trên tiến trình nào
Bridge RPC sẽ xử lý toàn bộ phần giao tiếp.


Lợi ích thực tế​

1. Tương thích lâu dài​

Các ứng dụng cũ như:

  • Excel VBA
  • Access VBA
  • VB6
vẫn có thể sử dụng các thư viện hiện đại được viết bằng:

  • Go
  • Delphi 64-bit
  • C++
  • Các DLL native khác

2. Không phụ thuộc kiến trúc​

Client 32-bit và 64-bit có thể sử dụng cùng một hệ thống.

3. Mở rộng dễ dàng​

Khi cần bổ sung chức năng mới:

  • Chỉ cần cập nhật DLL phía server.
  • Không cần biên dịch lại VBA hoặc VB6.

4. Hiệu năng cao​

Giao tiếp sử dụng TCP nội bộ và lời gọi native function.

Không sử dụng COM hoặc REST nên chi phí xử lý thấp.


Các hướng ứng dụng​

Bridge RPC có thể được sử dụng cho:

  • Hệ thống Plugin
  • Excel Automation
  • Access Database Tools
  • ERP nội bộ
  • Kết nối VBA với Go
  • Kết nối VB6 với DLL hiện đại
  • Dynamic DLL Loader
  • Native RPC Framework

Kết luận​

Bridge RPC được xây dựng với mục tiêu tạo ra một lớp tương thích chung giữa các ngôn ngữ lập trình và các kiến trúc khác nhau.

Thay vì phụ thuộc vào ABI của compiler hoặc giới hạn 32-bit / 64-bit, hệ thống sử dụng một lớp Runtime Invocation và RPC trung gian để tách biệt hoàn toàn:

  • Ngôn ngữ lập trình
  • Compiler
  • ABI
  • Kiến trúc hệ thống
Nhờ đó các ứng dụng cũ như VBA và VB6 vẫn có thể tận dụng các thư viện hiện đại mà không cần thay đổi kiến trúc hiện có.

Dự án hiện vẫn đang trong quá trình hoàn thiện và mở rộng, nhưng các thử nghiệm thực tế cho thấy mô hình này hoạt động ổn định trên nhiều ngôn ngữ và môi trường khác nhau.
 
Lần chỉnh sửa cuối:
Keo ChatGPT viết bài sau cho dân lập trình đọc

Bridge RPC & BridgeInvoker64​

Xây dựng Runtime Invocation Engine cho Windows​

Giới thiệu​

Trong quá trình phát triển phần mềm, tôi thường xuyên gặp các bài toán tích hợp giữa nhiều công nghệ khác nhau như VBA, VB6, Delphi, C++ Builder và Go.

Khó khăn lớn nhất thường không nằm ở nghiệp vụ mà nằm ở việc giao tiếp giữa các môi trường thực thi khác nhau:

  • VBA 32-bit không thể gọi trực tiếp DLL 64-bit.
  • VB6 chỉ hoạt động trong môi trường 32-bit.
  • Nhiều thư viện hiện đại được xây dựng cho nền tảng 64-bit.
  • Mỗi compiler có cách triển khai khác nhau.
  • Việc duy trì nhiều lớp wrapper làm tăng đáng kể độ phức tạp của hệ thống.
Từ nhu cầu thực tế đó, tôi xây dựng một hệ thống có tên Bridge RPC cùng thành phần lõi là BridgeInvoker64.dll.

Mục tiêu là tạo ra một lớp trung gian giúp các ứng dụng thuộc nhiều ngôn ngữ và môi trường khác nhau có thể sử dụng chung các thư viện native thông qua một giao thức thống nhất.


Bài toán​

Thông thường khi gọi một hàm trong DLL, chương trình phải biết chính xác chữ ký hàm tại thời điểm biên dịch.

Ví dụ:
int Add(int A, int B);

double Mul(double A, double B);

int64_t Sum(
int64_t A1,
int64_t A2,
int64_t A3,
int64_t A4,
int64_t A5);

Sau đó phải lấy địa chỉ hàm, ép kiểu Function Pointer và thực hiện lời gọi tương ứng.

typedef int (*TAdd)(int, int);

TAdd fn = (TAdd)GetProcAddress(...);

Result = fn(10, 20);

Phương pháp này hoàn toàn phù hợp đối với các DLL có interface cố định.

Tuy nhiên khi xây dựng:

  • Plugin Framework
  • Dynamic Loader
  • RPC System
  • Runtime Extension System
thì số lượng wrapper cần duy trì sẽ tăng lên rất nhanh.


Ý tưởng​

Bridge RPC chuyển lời gọi hàm thành metadata thay vì gọi trực tiếp.

Ví dụ một lời gọi hàm có thể được mô tả như sau:

Function : AddI64

Arguments
----------
Arg0 : I64 = 10
Arg1 : I64 = 20
Arg2 : I64 = 30
Arg3 : I64 = 40
Arg4 : I64 = 50

Return Type
-----------
I64

Lúc này lời gọi hàm đã trở thành dữ liệu.

BridgeInvoker64.dll sẽ đọc metadata, xây dựng môi trường thực thi phù hợp và thực hiện lời gọi tại runtime.


Kiến trúc hệ thống​

Bridge RPC được thiết kế theo mô hình client-server.

Phía client có thể là:

  • VBA
  • VB6
  • Delphi
  • C++ Builder
  • Go
Các ứng dụng client giao tiếp với BridgeServer thông qua giao thức RPC.

BridgeServer tiếp nhận yêu cầu, nạp DLL nghiệp vụ, sau đó chuyển lời gọi cho BridgeInvoker64.dll thực thi.

Nhờ đó phía client hoàn toàn không cần biết DLL nghiệp vụ được xây dựng bằng công nghệ nào.


BridgeInvoker64.dll là gì?​

BridgeInvoker64.dll được phát triển bằng C++ Builder và là thành phần quan trọng nhất của toàn bộ hệ thống.

Nhiệm vụ chính của nó bao gồm:

  • Nhận Function Pointer.
  • Nhận danh sách tham số.
  • Nhận mô tả kiểu dữ liệu.
  • Chuẩn bị môi trường thực thi.
  • Thực hiện lời gọi hàm.
  • Thu nhận giá trị trả về.
Có thể xem BridgeInvoker64.dll như một Runtime Invocation Engine dành cho Windows x64.


Dynamic ABI Invocation​

Thay vì gọi trực tiếp:

Add(10, 20);<br>
BridgeInvoker64.dll nhận:

  • Function Pointer
  • Argument List
  • Type Information
Sau đó tự động:

  • Chuẩn bị tham số.
  • Đưa tham số vào thanh ghi phù hợp.
  • Xử lý tham số mở rộng trên stack.
  • Thực hiện lời gọi hàm.
  • Thu nhận kết quả trả về.
Toàn bộ quá trình được thực hiện tại runtime.

Nhờ đó một cơ chế thực thi duy nhất có thể phục vụ cho rất nhiều hàm khác nhau mà không cần viết wrapper riêng.


Kiểu dữ liệu hỗ trợ​

Phiên bản hiện tại hỗ trợ:

  • I32
  • U32
  • I64
  • U64
  • PTR
  • F64
Hệ thống hiện hỗ trợ tối đa 16 tham số cho một lời gọi hàm.

Các bài kiểm thử hiện tại bao gồm:

  • AddI32
  • AddI64
  • MulF64
  • MixF64I64
  • Sum10
  • Sum16
với nhiều tổ hợp tham số khác nhau.


Không phụ thuộc ngôn ngữ phía client​

Các thử nghiệm hiện tại đã được thực hiện với:

  • VB6
  • VBA 32-bit
  • VBA 64-bit
  • Delphi
  • Go
Tất cả đều sử dụng cùng một giao thức RPC.

Không cần viết lại DLL nghiệp vụ cho từng môi trường.


Tách biệt client và server​

Một trong những mục tiêu quan trọng nhất của hệ thống là tách biệt hoàn toàn client khỏi môi trường thực thi phía server.

Ví dụ:

Một ứng dụng VBA 32-bit vẫn có thể sử dụng các chức năng được triển khai trong Go DLL 64-bit thông qua Bridge RPC.

Tương tự, một ứng dụng VB6 vẫn có thể sử dụng DLL được xây dựng bằng Delphi 64-bit mà không cần thay đổi mã nguồn phía client.

Trong cả hai trường hợp, phía client không cần biết DLL đích được biên dịch bằng ngôn ngữ nào hoặc đang chạy trên kiến trúc nào. Toàn bộ quá trình giao tiếp và thực thi được Bridge RPC xử lý ở tầng trung gian.


Các hướng ứng dụng​

Kiến trúc này có thể áp dụng cho:

  • Plugin Framework
  • Automation Platform
  • ERP nội bộ
  • Excel Backend
  • Access Backend
  • Dynamic DLL Loader
  • Native RPC Runtime
  • Cross-Language Integration
  • Hệ thống kiểm thử tự động

Một số công nghệ có ý tưởng tương đồng​

Khái niệm Runtime Invocation không phải là mới.

Nhiều công nghệ nổi tiếng đã áp dụng các cơ chế tương tự như:

  • libffi
  • dyncall
  • Python ctypes
  • LuaJIT FFI
  • .NET P/Invoke
Tuy nhiên BridgeInvoker64.dll được xây dựng với mục tiêu tập trung vào nền tảng Windows và khả năng tích hợp với các ứng dụng doanh nghiệp đang sử dụng VBA, VB6, Delphi và C++ Builder.


Kết luận​

Bridge RPC không đơn thuần là một thư viện giao tiếp TCP và cũng không chỉ là một DLL wrapper.

Mục tiêu của dự án là xây dựng một lớp Runtime Invocation giúp tách biệt:

  • Ngôn ngữ lập trình.
  • Môi trường thực thi.
  • Cơ chế giao tiếp.
  • Chi tiết triển khai của DLL nghiệp vụ.
Nhờ đó các ứng dụng được phát triển từ nhiều thế hệ công nghệ khác nhau vẫn có thể sử dụng chung các thư viện native hiện đại thông qua một cơ chế giao tiếp thống nhất.

Đối với tôi, giá trị lớn nhất của dự án không nằm ở việc VBA gọi được DLL 64-bit, mà nằm ở việc tạo ra một lớp trung gian giúp các hệ thống khác nhau có thể cộng tác với nhau mà không bị ràng buộc chặt vào ngôn ngữ, compiler hoặc kiến trúc triển khai cụ thể.
 

Bài viết mới nhất

Back
Top Bottom