yao518 2023-08-12 15:12 采纳率: 20%
浏览 7

谁会GOLANG和pascal这二种语言,我想把一个GO写的开源项目翻译成pascal

谁会GOLANG和pascal这二种语言,我想把一个GO写的开源项目翻译成pascal

调用wintun.dll单元


unit WinTun;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, Windows, SysUtils, JwaWindows, Dialogs, WinUnit, Win32Proc;

const
  //用于接收和发送数据包的内存区域大小
  WINTUN_MIN_RING_CAPACITY = $20000;       //128kiB
  WINTUN_MAX_RING_CAPACITY = $4000000;     //64MiB

  //最大IP数据包大小常量。IP数据包是在网络中传输的数据单元,它包含了源IP地址、目标IP地址、协议类型、数据等信息
  WINTUN_MAX_IP_PACKET_SIZE = $FFFF;       //65535

type
  WINTUN_ADAPTER_HANDLE = Pointer;
  WINTUN_SESSION_HANDLE = Pointer;
  WINTUN_LOGGER_LEVEL = (WINTUN_LOG_INFO, WINTUN_LOG_WARN, WINTUN_LOG_ERR);

  WINTUN_CREATE_ADAPTER_FUNC = function(Name: LPCWSTR; TunnelType: LPCWSTR; RequestedGUID: PGUID): WINTUN_ADAPTER_HANDLE; stdcall;
  WINTUN_OPEN_ADAPTER_FUNC = function(Name: LPCWSTR): WINTUN_ADAPTER_HANDLE; stdcall;
  WINTUN_CLOSE_ADAPTER_PROC = procedure(Adapter: WINTUN_ADAPTER_HANDLE); stdcall;
  WINTUN_DELETE_DRIVER_FUNC = function: BOOL; stdcall;
  WINTUN_GET_ADAPTER_LUID_PROC = procedure(Adapter: WINTUN_ADAPTER_HANDLE; Luid: PNET_LUID_LH); stdcall;
  //几乎所有的编程语言都需要在函数调用时使用括号,无论函数是否有参数(形参)。这是因为括号是函数调用的一部分,它们用于标识函数的名称和参数列表
  WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC = function(): DWORD; stdcall;
  WINTUN_LOGGER_CALLBACK_PROC = procedure(Level: WINTUN_LOGGER_LEVEL; Timestamp: DWORD64; Message: pwidechar); stdcall;
  WINTUN_SET_LOGGER_PROC = procedure(NewLogger: WINTUN_LOGGER_CALLBACK_PROC); stdcall;
  WINTUN_START_SESSION_FUNC = function(Adapter: WINTUN_ADAPTER_HANDLE; Capacity: DWORD): WINTUN_SESSION_HANDLE; stdcall;
  WINTUN_END_SESSION_PROC = procedure(Session: WINTUN_SESSION_HANDLE); stdcall;
  WINTUN_GET_READ_WAIT_EVENT_FUNC = function(Session: WINTUN_SESSION_HANDLE): HANDLE; stdcall;
  //删除PacketSize的var保留字,因为用@来指向这个形参,也算引用,与var功能差不多
  WINTUN_RECEIVE_PACKET_FUNC = function(Session: WINTUN_SESSION_HANDLE; PacketSize: PDWORD): pbyte; stdcall;
  WINTUN_RELEASE_RECEIVE_PACKET_PROC = procedure(Session: WINTUN_SESSION_HANDLE; Packet: pbyte); stdcall;
  WINTUN_ALLOCATE_SEND_PACKET_FUNC = function(Session: WINTUN_SESSION_HANDLE; PacketSize: DWORD): pbyte; stdcall;
  WINTUN_SEND_PACKET_PROC = procedure(Session: WINTUN_SESSION_HANDLE; Packet: pbyte); stdcall;

var
  WintunCreateAdapter: WINTUN_CREATE_ADAPTER_FUNC;
  WintunOpenAdapter: WINTUN_OPEN_ADAPTER_FUNC;
  WintunCloseAdapter: WINTUN_CLOSE_ADAPTER_PROC;
  WintunDeleteDriver: WINTUN_DELETE_DRIVER_FUNC;
  WintunGetAdapterLUID: WINTUN_GET_ADAPTER_LUID_PROC;
  WintunGetRunningDriverVersion: WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC;
  WintunSetLogger: WINTUN_SET_LOGGER_PROC;
  WintunStartSession: WINTUN_START_SESSION_FUNC;
  WintunEndSession: WINTUN_END_SESSION_PROC;
  WintunGetReadWaitEvent: WINTUN_GET_READ_WAIT_EVENT_FUNC;
  WintunReceivePacket: WINTUN_RECEIVE_PACKET_FUNC;
  WintunReleaseReceivePacket: WINTUN_RELEASE_RECEIVE_PACKET_PROC;
  WintunAllocateSendPacket: WINTUN_ALLOCATE_SEND_PACKET_FUNC;
  WintunSendPacket: WINTUN_SEND_PACKET_PROC;

implementation

const
  WintunDll = 'wintun.dll';

var
  WintunModule: HMODULE;

procedure LoadWintunLibrary;
var
  ErrorCode: DWORD;
begin
  //https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
  WintunModule := LoadLibraryExW(WintunDll, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
  //https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
  if WintunModule = NULL then
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Exit;
  end;

  //注意调用C++ dll方法名称,C++是大小写敏感的
  Pointer(WintunCreateAdapter) := GetProcAddress(WintunModule, 'WintunCreateAdapter');                      //创建适配器的函数
  Pointer(WintunOpenAdapter) := GetProcAddress(WintunModule, 'WintunOpenAdapter');                          //打开适配器的函数
  Pointer(WintunCloseAdapter) := GetProcAddress(WintunModule, 'WintunCloseAdapter');                        //关闭适配器的函数
  Pointer(WintunDeleteDriver) := GetProcAddress(WintunModule, 'WintunDeleteDriver');                        //删除驱动程序的函数
  Pointer(WintunGetAdapterLUID) := GetProcAddress(WintunModule, 'WintunGetAdapterLUID');                    //获取适配器LUID的函数
  Pointer(WintunGetRunningDriverVersion) := GetProcAddress(WintunModule, 'WintunGetRunningDriverVersion');  //获取运行中驱动程序版本的函数
  Pointer(WintunSetLogger) := GetProcAddress(WintunModule, 'WintunSetLogger');                              //设置日志记录回调函数的函数
  Pointer(WintunStartSession) := GetProcAddress(WintunModule, 'WintunStartSession');                        //启动会话的函数,返回Wintun 会话句柄
  Pointer(WintunEndSession) := GetProcAddress(WintunModule, 'WintunEndSession');                            //结束会话的函数
  Pointer(WintunGetReadWaitEvent) := GetProcAddress(WintunModule, 'WintunGetReadWaitEvent');                //获取wintun会话的读取等待事件的函数
  Pointer(WintunReceivePacket) := GetProcAddress(WintunModule, 'WintunReceivePacket');                      //接收数据包的函数
  Pointer(WintunReleaseReceivePacket) := GetProcAddress(WintunModule, 'WintunReleaseReceivePacket');        //释放接收数据包的函数
  Pointer(WintunAllocateSendPacket) := GetProcAddress(WintunModule, 'WintunAllocateSendPacket');            //分配发送数据包的函数
  Pointer(WintunSendPacket) := GetProcAddress(WintunModule, 'WintunSendPacket');                            //发送数据包的函数

  ErrorCode := GetLastError;
  if ErrorCode <> NO_ERROR then
    //调用的这个方法https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-formatmessagew
    ShowMessage(SysErrorMessage(ErrorCode));
end;

initialization
  LoadWintunLibrary;

  //finalization部分在程序退出时执行的,而不是手动调用的。
  //因此,如果需要在程序运行过程中进行资源释放或其他清理操作,应该在适当的位置手动调用相应的代码
finalization
  if not UnloadLibrary(WintunModule) then
    ShowMessage(SysErrorMessage(GetLastError));

end.

调用windows API 单元


unit WinUnit;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, windows, SysUtils, Dialogs, JwaWindows;

type
  SOCKADDR_INET = record
    case integer of
      0: (Ipv4: SOCKADDR_IN);
      1: (Ipv6: SOCKADDR_IN6);
      2: (si_family: word);
  end;
  PSOCKADDR_INET = ^SOCKADDR_INET;

  //https://learn.microsoft.com/zh-cn/windows/win32/api/ifdef/ns-ifdef-net_luid_lh
  NET_LUID_LH = record
    case integer of
      0: (Value: uint64);
      1: (Info: record
          Reserved: uint64;
          NetLuidIndex: uint64;
          IfType: word;
          end);
  end;
  PNET_LUID_LH = ^NET_LUID_LH;

  NL_PREFIX_ORIGIN = (
    IpPrefixOriginOther = 0,
    IpPrefixOriginManual,
    IpPrefixOriginWellKnown,
    IpPrefixOriginDhcp,
    IpPrefixOriginRouterAdvertisement,
    IpPrefixOriginUnchanged = 1 shl 4);

  NL_SUFFIX_ORIGIN = (
    IpSuffixOriginOther = 0,
    IpSuffixOriginManual,
    IpSuffixOriginWellKnown,
    IpSuffixOriginDhcp,
    IpSuffixOriginLinkLayerAddress,
    IpSuffixOriginRandom,
    IpSuffixOriginUnchanged = 1 shl 4);

  //https://learn.microsoft.com/zh-cn/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row#members
  MIB_UNICASTIPADDRESS_ROW = record
    Address: SOCKADDR_INET;
    InterfaceLuid: NET_LUID_LH;
    InterfaceIndex: DWORD;
    PrefixOrigin: NL_PREFIX_ORIGIN;
    SuffixOrigin: NL_SUFFIX_ORIGIN;
    ValidLifetime: ULONG;
    PreferredLifetime: ULONG;
    OnLinkPrefixLength: uint8;  //子网掩网长度
    SkipAsSource: boolean;
    DadState: IP_DAD_STATE;
    ScopeId: LARGE_INTEGER;
    CreationTimeStamp: LARGE_INTEGER;
  end;
  PMIB_UNICASTIPADDRESS_ROW = ^MIB_UNICASTIPADDRESS_ROW;

var
  //var修饰符表示参数是一个引用。对于指针类型的参数,使用var修饰符是不允许的,因为指针本身就是引用类型。
  InitializeUnicastIpAddressEntry: procedure(PROW: PMIB_UNICASTIPADDRESS_ROW); stdcall;
  CreateUnicastIpAddressEntry: function(const PROW: PMIB_UNICASTIPADDRESS_ROW): DWORD; stdcall;
  SetUnicastIpAddressEntry: function(const PROW: PMIB_UNICASTIPADDRESS_ROW): DWORD;
  //将 IPv6 地址转换为 Internet 标准格式的字符串
  RtlIpv6AddressToStringW: function(const Addr: PIn6Addr; S: pwidechar): pwidechar; stdcall;

implementation

var
  IPHLPAPIModule: HMODULE;
  IPV6AddressTOSTRModule: HMODULE;
  SetUnicastIpAddressEntryModule: HMODULE;

procedure LoadWinLibrary;
var
  ErrorCode: DWORD;
begin
  IPHLPAPIModule := LoadLibraryExW(iphlpapilib, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
  if IPHLPAPIModule = NULL then
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Exit;
  end;

  IPV6AddressTOSTRModule := LoadLibraryExW(Ntdll, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
  if IPV6AddressTOSTRModule = NULL then
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Exit;
  end;

  SetUnicastIpAddressEntryModule := LoadLibraryEx(iphlpapilib, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
  if SetUnicastIpAddressEntryModule = NULL then
  begin
    ShowMessage(SysErrorMessage(GetLastError));
    Exit;
  end;

  Pointer(InitializeUnicastIpAddressEntry) := GetProcAddress(IPHLPAPIModule, 'InitializeUnicastIpAddressEntry');   //初始化PMIB_UNICASTIPADDRESS_ROW结构体
  Pointer(CreateUnicastIpAddressEntry) := GetProcAddress(IPHLPAPIModule, 'CreateUnicastIpAddressEntry');           //此函数在本地设备上添加新的单播 IP 地址条目,如果函数成功,则返回值0
  Pointer(RtlIpv6AddressToStringW) := GetProcAddress(IPV6AddressTOSTRModule, 'RtlIpv6AddressToStringW');           //以 Internet 标准格式将 IPv6 地址转换为字符串
  Pointer(SetUnicastIpAddressEntry) := GetProcAddress(SetUnicastIpAddressEntryModule, 'SetUnicastIpAddressEntry'); //设置IP相关数据

  ErrorCode := GetLastError;
  if ErrorCode <> NO_ERROR then
    //调用的这个方法https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-formatmessagew
    ShowMessage(SysErrorMessage(ErrorCode));
end;

initialization
  LoadWinLibrary;

finalization;
  if not UnloadLibrary(IPHLPAPIModule) then
    ShowMessage(SysErrorMessage(GetLastError));

  if not UnloadLibrary(IPV6AddressTOSTRModule) then
    ShowMessage(SysErrorMessage(GetLastError));

  if not UnloadLibrary(SetUnicastIpAddressEntryModule) then
    ShowMessage(SysErrorMessage(GetLastError));

end.

上面我自己写的PASCAL源码,有打算把 WireGuard 翻译成 pascal ,GO语言有点看不懂,如果有懂 GO 语言和 pascal 的可以交流一下!

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-08-12 18:56
    关注

    【以下回答由 GPT 生成】

    常见的优化问题有很多,可以是关于算法的优化、性能的优化、数据库的优化等等。请您提供一些更具体的细节,例如具体是哪个方面需要优化、目前遇到了什么问题、需要达到什么样的优化效果等等。这样我才能给出更具针对性的解决方案。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 修改了问题 8月13日
  • 修改了问题 8月13日
  • 创建了问题 8月12日

悬赏问题

  • ¥15 echarts动画效果的问题,请帮我添加一个动画。不要机器人回答。
  • ¥60 许可证msc licensing软件报错显示已有相同版本软件,但是下一步显示无法读取日志目录。
  • ¥15 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加