编译wxWidgets及libwx-c.so (libwx-c-0-9-0-2.so) 的经历与体会

文章讲述了作者对wx-c库进行升级编译的过程,涉及wxWidgets版本差异、依赖库管理、64位移植挑战以及FreeBasic的使用。作者分享了从源代码学习、工具安装、编译错误处理和ABI版本统一等关键步骤和体会。
摘要由CSDN通过智能技术生成

序言

近期针对 wx-c 库进行更新编译,对wxWidgets相关软件和配置方式进行了更多了解和体验。wxWidgets本来叫 wxWindows, 因为名称与微软 windows 太过相近,因此微软律师出面进行了善意和解,wxWindows随即更名为 wxWidgets,早期是在wxBase基本库上逐步扩展的, wxBase 主要解决数据类型、转换、结构等方面的基础工作,组件是在 motif, x11, gtk, 甚至qt上做的,但后来默认的就是gtk了,x11和motif样式确实过于精典。如果在linux平台上只是做界面,gtk界面库已经非常丰富了,但在windows平台上基于本地sdk做的组件肯定看上去更 native, 所以我个人认为 wxWidgets 在 Windows 平台上优势更多一些。无论如何,它还是将平台底层与用户程序隔离开来了,不再像过渡期的 mfc 和 sdk 混在一起,封装比较浅。过度封装的好处可以简化操作,但坏处是离底层越来越远而不断失去深入底层玩味的机会。

wx-c是wxNET的底层,是一套c方式的wxWidgets封装,在它上在又封装了wxNET库,同时wx-c封装后.h又被转换成freebasic的.bi,实际上,wx-c也同样能被其它编译语言使用。FreeBasic有wx-c完整的头文件,但没有相应的libwx-c文件,网上能找到的也只有ELF32格式的 libwx-c-0-9-0-2.so ,很长时间的停更原因不得而知。我的想法是既然有头文件,有wxWidgets和wx-c源代码,就做点工作将它从32位升到64位,让它能在64位系统上继续使用。于是,就走入wxWidgets百有园,获得经历和思考,又于是有了一些新体会。

经历1:在sourceforge下载wx.NET源代码后学习

体会:wx-c 源代码是cxx的,有145个文件和一个wx-c.make文件。直接make -f wx-c.make后错误和提示覆盖了屏幕,这说明加.o都不能生成,更别指望生成.so了。打开make文件和程序源码,最终找到了它是wxWidgets 2.8版本上做的封装,不可能直接使用wxWidgets3.2.4, 因主wxWidgets3.2.4的函数和类与wxWidgets 2.8已经非常不相同了,wx-c要继承的类已经没有了,有些函数也没有了,而它有的与现在的又对应不上,这一百多个文件要是改起来,是不行不行的。但,既然研究了,就更深入一点,于是:

安装 wxformbuilder, codelite, codeblocks ,反正就是 sudo apt install, 在线安装也方便。安装后想创建个wxWidgets应用,看看窗体创建和类继承代码,但是,它们不运行,说是需要wxWidgets 3.0.5 支持。于是,下载wxWidget 3.0.5, 用的gcc是11.4版本。

./configure --enable-unicode --with-gtk=3

make && sudo make install

编译安装顺利,再运行wxformbuilder 3.9, 顺利。放个frame, 放个sizer, 再放上两个button, 查看c++代码,frame类和函数继承就看清了,对比wx-c源代码,做的工作几乎是一样的,其它函数也基本上是对等映射的。因此,在c上会操练wxWidget, 经过wx-c封装后也就会操作,反之亦然,所以它封装的并不是很完全。

经历2:安装libwx-gtk2u.xxx库文件与编译wxGTK2.8.12文件

既然wx-c用的是wxWidgets2.8的库,于是apt search查找libwx-gtk2u相关lib, 本地没有到pkg和debian库上找旧的下载、解压后放到自己的lib路径下,但因缺少 wx-c.o 而不能使用它们,还是要自己编译它们才行。

1.  ./configure --enable-unicode --with-gtk=2

2. make

开始编译,警告信息不少,但基本上都是善意的,因此不予采。到了va_copy时,就编译出错进行不下去了。显示原作者编译是没问题的,现在出了问题,说明编译器版本太新。查了一下那个时期的编译器,让现在的编译器兼容到 -std=c99 , -std=c++98 ,将写修改到 make 文件中,然后继续 make。

体会:前期生的.o继续保留,从错误处继续产生新的.o文件,虽然它们编译时的参数不同,但link时不影响。遇上错误修改 Makefile 文件,但不要 make clean 从头编译,那样前期的文件又编译不过去了,逢山开路遇水搭桥直接向前,就没什么问题了。

经历3:对ABI版本不同的处理

考虑到原来有了一些libwx-gtk2u的库文件,于是只将新生成的libwx-c.so又考贝了过去,修改freebasic 自带的 wx-c.bi 中的库引用为 #inclib wx-c ,试运行提示缺少一些libwx-gtk库,那就用刚生成的库按提示信息补进去,于是缺的又考进去了。再运行,提示先考贝进去库的 ABI是1009, 而后考进去的库是 1016

体会:即使文件名相同由于ABI版本不同也不能使用,必须统一到相同ABI版本。即然原来找的那些库是 1009的,那就修改Makefile, 编译时再加上一个参数 -fabi-version=09, 再编译,编译后将缺的那几个库文件考过去,再运行sample程序,顺利运行。其实早该全考过去,不用原考进去的那些库,也就不会遇到 ABI 问题了。

运行Visual_WX-C_Designer, Visual_WX-C_Designer.sh, 或wine Visual_WX-C_Designer.exe

Visual_WX-C_Designer是基于wx-c的Designer, 它的linux版本是 Visual_WX-C_Designer, 那个 Visual_WX-C_Designer.sh 调用的还是linux版本的 Visual_WX-C_Designer, 不同的是加上了库的路径,这样运行的共享库放在本地即可,不用放在/usr/lib或/usr/local/lib里混在一起。

#! /bin/bash
export LD_LIBRARY_PATH="./lib"
./Visual_WX-C_Designer

Visual_WX-C_Designer.exe是Win32版本的设计器,它需要wine支持,因为它非常精简,所以运行起来与linux本地程序没有什么太大不同,但似乎显示效果更好一些。下图左上是linux版本,右下是wine 支持的win32版本,它们都是32位版本的。

生成的代码质量挺好

#Include Once "wx-c/wx.bi"

Declare Function App_OnInit WXCALL ( ) As wxBool
Declare Function App_OnExit WXCALL ( ) As wxInt

Declare Sub button0_event WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
Declare Sub button1_event WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
Declare Sub menuhandler WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
''
'' Translate FBString to wxString
''
Function fbstring_to_wxString( ByVal fbstr As String ) As wxString Ptr
	Dim As wxString Ptr ret
	ret = wxString_ctorUTF8( fbstr )
	Return ret
End Function

''
'' Translate wxString to FBString
''
Function wxString_to_fbstring( ByVal wxstr As wxString Ptr ) As String
	Dim As String ret
	Dim As Integer i
	For i = 0 To wxString_GetLength( wxstr )
		If wxString_CharAtUTF16( wxstr, i ) <> 0 Then
			ret += Chr( wxString_CharAtUTF16( wxstr, i ) )
		EndIf
	Next
	Return ret
End Function


Dim Shared As wxApp Ptr wx_app
Dim Shared As wxFrame Ptr wx_frame
Dim Shared As wxPanel Ptr wx_panel

Function App_OnInit WXCALL ( ) As wxBool
	
	wx_frame = wxFrame_ctor( )
	wxImage_InitAllHandlers( )
	
	wxFrame_Create( wx_frame, WX_NULL, -1, fbstring_to_wxString(( "" )), 427, 340, 705, 498, wxFRAME_DEFAULT_STYLE Or wxCLOSE_BOX Xor wxMAXIMIZE_BOX Xor wxRESIZE_BORDER, WX_NULL )
	wx_panel = wxPanel_ctor2( wx_frame, -1, -1, -1, -1, -1, 0, WX_NULL )
	
	'' Application Icon
	Dim As wxIcon Ptr wx_icon
	Dim As wxBitmap Ptr iconImage
	wx_icon = wxIcon_ctor( )
	iconImage = wxBitmap_ctor( )
	wxBitmap_LoadFile( iconImage, fbstring_to_wxString(( "/home/songyq/myApplication/poseidonFB-freebasic/fblogo.png" )), wxBITMAP_TYPE_PNG )
	wxIcon_CopyFromBitmap( wx_icon, iconImage )
	wxFrame_SetIcon( wx_frame, wx_icon )
	
	''
	'' create widget button0
	''
	Dim As wxButton Ptr button0
	button0 = wxButton_ctor( )
	wxButton_Create( button0, wx_panel, -1, fbstring_to_wxString(( "button0" )), 200, 110, 340, 50, 0, 0, 0 )
	
	wxEvtHandler_Proxy( button0, Cast(EventListener, @button0_event) )
	wxEvtHandler_Connect( button0, wxEvent_EVT_COMMAND_BUTTON_CLICKED( ), -1, -1, 0 )
	
	''
	'' create widget textctrl0
	''
	Dim As wxTextCtrl Ptr textctrl0
	textctrl0 = wxTextCtrl_ctor( )
	wxTextCtrl_Create( textctrl0, wx_panel, -1, fbstring_to_wxString(( "textctrl0" )), 100, 230, 340, 50, 0, 0, 0 )
	
	
	''
	'' create widget button1
	''
	Dim As wxButton Ptr button1
	button1 = wxButton_ctor( )
	wxButton_Create( button1, wx_panel, -1, fbstring_to_wxString(( "button1" )), 230, 330, 370, 50, 0, 0, 0 )
	
	wxEvtHandler_Proxy( button1, Cast(EventListener, @button1_event) )
	wxEvtHandler_Connect( button1, wxEvent_EVT_COMMAND_BUTTON_CLICKED( ), -1, -1, 0 )
	
	
	'' create menus
	Dim As wxMenuBar Ptr wx_menubar
	wx_menubar = wxMenuBar_ctor( )
	
	
	'' menu "&Menu 0"
	Dim As wxMenu Ptr wx_menu0
	wx_menu0 = wxMenu_ctor( fbstring_to_wxString(( "" )), 0 )
	wxMenuBase_AppendCheckItem( wx_menu0, 1, fbstring_to_wxString(( "checkitem0" )), fbstring_to_wxString(( "checkitem0" )) )
	wxMenuBase_AppendRadioItem( wx_menu0, 2, fbstring_to_wxString(( "radioitem1" )), fbstring_to_wxString(( "radioitem1" )) )
	wxMenuBase_AppendSeparator( wx_menu0 )
		
		'' menu "submenuitem3"
		Dim As wxMenu Ptr wx_menu1
		wx_menu1 = wxMenu_ctor( fbstring_to_wxString(( "" )), 0 )
		wxMenuBase_AppendCheckItem( wx_menu1, 3, fbstring_to_wxString(( "checkitem0" )), fbstring_to_wxString(( "checkitem0" )) )
	
	wxMenuBase_AppendSubMenu( wx_menu0, 4, fbstring_to_wxString(( "submenuitem3" )), wx_menu1, fbstring_to_wxString(( "submenuitem3" )) )
	wxMenuBar_Append( wx_menubar, wx_menu0, fbstring_to_wxString(( "&Menu 0" )) )
	wxFrame_SetMenuBar(wx_frame, wx_menubar)
	
	
	
	wxFrame_CreateToolbar( wx_frame, wxHORIZONTAL Or wxTB_TEXT Or wxTB_FLAT, -1, 0 )
	wxToolBar_Realize( wxFrame_GetToolbar( wx_frame ) )
	
	wxEvtHandler_Proxy( wx_frame, Cast(EventListener, @menuhandler) )
	wxEvtHandler_Connect( wx_frame, wxEvent_EVT_COMMAND_MENU_SELECTED( ), -1, -1, 0 )
	
	
	wxWindow_Show( wx_frame, 1 )
	wxApp_OnInit( wx_app )
	Return 1
	
End Function

Function App_OnExit WXCALL ( ) As wxInt
	
	Return wxApp_OnExit( wx_app )
	
End Function

Sub button0_event WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
	
	Select Case wxEvent_GetEventType( event )
		Case wxEvent_EVT_COMMAND_BUTTON_CLICKED
			''add event handler code here
			wxWindow_Destroy(wx_frame)
	End Select
	
End Sub

Sub button1_event WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
	
	Select Case wxEvent_GetEventType( event )
		Case wxEvent_EVT_COMMAND_BUTTON_CLICKED
			''add event handler code here
			
	End Select
	
End Sub

Sub menuhandler WXCALL ( ByVal event As wxEvent Ptr, ByVal iListener As wxInt )
	
	Select Case wxEvent_GetId( event )
		Case 1
			'' add event handler code for selecting check item checkitem0 from menu &Menu 0 goes here
			
		Case 2
			'' add event handler code for selecting radio item radioitem1 from menu &Menu 0 goes here
			
		Case 3
			'' add event handler code for selecting check item checkitem0 from menu submenuitem3 goes here
			
	End Select
	
End Sub


''main
wx_app = wxApp_ctor( )
wxApp_RegisterVirtual ( wx_app, @App_OnInit, @App_OnExit )
wxApp_Run( 0, 0 )

基于WX-C的IDE开发环境 wxFBE

它也是32位版本的,支持多语言,我加了中文改了几行没再多修改。

基于wx-c的IDE是32位的,但fbc编译出的程序是64位的,IDE用的库放在本地即可,不用放到操作系统的库路径中。

将生成的wxWidgets 2.8的 64位库和 libwx-c.so放在一起打了个包(wx是wxWidgets 2.8版的配置文件,和lib库文件放在一起,wx文件夹下不同版本的wxWidgets都会在那里面,wx-configure --version=nn 时就会自动为其它程序配置nn版本的wxWidget)

写改写wx-c到wxWidget3.2.4新版本wx-c的话,除了会修改函数,还会涉及到增加新函数,麻烦的是freebasic的头文件也要改,相应的示例程序也要改,开源的32位的设计器也要改(IDE不用改,它使用的设计器是个Visual_WX-C_Designer的plugin, 编译器是 fbc),暂时没有改动它们的想法。由于wxWidget和gtk是多平台的,用wx-c写的程序在三个主流平台上运行应该不会有障碍的。

编译好的64位wxWidgets2.8.12和wx-c-0-9-0-2库放在CSDN了供下载icon-default.png?t=N7T8https://download.csdn.net/download/weixin_45707491/89095738

In case of access failure, below package link may be accessed.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值