question on call functions in DLL

Windows specific questions.
oyster
Posts: 274
Joined: Oct 11, 2005 10:46

question on call functions in DLL

Post by oyster »

in the following code, there are 1 error and 1 warning
1. the error occurs on line 32

Code: Select all

res = XC_MessageBox(0, "Hello", "pCaption", 1)
if I comment out it, there is no error. But I have defined XC_MessageBox on line 20. So what does this error mean?

2. the warning is on line 48

Code: Select all

@OnClick
. How can I change it to the real pointer as C header says

Code: Select all

XC_API BOOL WINAPI XEle_RegEventC(HELE hEle, int nEvent, void *pFun);
How to fix it ? Thnaks

Code: Select all

Dim As Any Ptr library = DyLibLoad("xcgui")

#define XE_BNCLICK  34

Dim XInitXCGUI As Function (ByVal pText As String) As Boolean
XInitXCGUI = DyLibSymbol(library, "XInitXCGUI")

Dim XWnd_Create As Function (ByVal x As Long,ByVal y As Long,ByVal cx As Long,ByVal cy As Long,ByVal pTitle As String,ByVal hWndParent As Long,ByVal XCStyle As Long) As Long
XWnd_Create = DyLibSymbol(library, "XWnd_Create")

Dim XBtn_Create As Function (ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal pName As String, ByVal hParent As Long) As Long
XBtn_Create = DyLibSymbol(library, "XBtn_Create")

Dim XEle_RegEventC As Function (ByVal hEle As Long, ByVal nEvent As Long, ByVal pFun As Long) As Boolean
XEle_RegEventC = DyLibSymbol(library, "XEle_RegEventC")

Dim XWnd_ShowWindow As Function (ByVal hWindow As Long,ByVal nCmdShow As Long) As Boolean
XWnd_ShowWindow = DyLibSymbol(library, "XWnd_ShowWindow")

Dim XC_MessageBox As Function(ByVal hWindow As Long, ByVal pText As String, ByVal pCaption As String, ByVal nFlags As Long) As Long
XC_MessageBox = DyLibSymbol(library, "XC_MessageBox")

Dim XRunXCGUI As Sub ()
XRunXCGUI = DyLibSymbol(library, "XRunXCGUI")

Dim XExitXCGUI As Sub ()
XExitXCGUI = DyLibSymbol(library, "XExitXCGUI")


Function OnClick(ByRef bHandle As Long) As Long
    Dim as Long res
    ' ~ res = XC_MessageBox(0, "Hello", "pCaption", 1)
    print "in OnClick"
    bHandle = True
    OnClick = 0
End Function

dim as Boolean bOk, bTmp
dim as LONG hWindow
dim as LONG hBtn

bOk = XInitXCGUI("")

If bOk Then
    hWindow = XWnd_Create(0, 0, 300, 200, ("demo"), 0, 3)

    hBtn = XBtn_Create( 8, 30, 100, 20, "button", hWindow )
    bTmp = XEle_RegEventC(hBtn, XE_BNCLICK, @OnClick)

    If hWindow <> 0 Then
        XWnd_ShowWindow( hWindow, 5 )
        XRunXCGUI()
    End If

    XExitXCGUI()

End If

DyLibFree(library)
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: question on call functions in DLL

Post by fxm »

2)

Code: Select all

    bTmp = XEle_RegEventC(hBtn, XE_BNCLICK, cast(Long, @OnClick))
1)
As for any variable, 'XC_MessageBox' must be declared 'Shared' if you want to call it from a procedure ('XC_MessageBox' is not a function name but a function pointer):

Code: Select all

Dim Shared XC_MessageBox As Function(ByVal hWindow As Long, ByVal pText As String, ByVal pCaption As String, ByVal nFlags As Long) As Long
  • (or pass it as an argument)
oyster
Posts: 274
Joined: Oct 11, 2005 10:46

Re: question on call functions in DLL

Post by oyster »

thanks. It fixes. But there are one further question. Since I declare the long APIs in a include file, for example "xcgui.bi"

Code: Select all

' I am "xcgui.bi"
Dim shared libray As Any Ptr
libray = DylibLoad("xcgui")

then tons of functions are declared
how can I do

Code: Select all

DyLibFree(library)
safely and elegantly?

currently I try to wrap the DylibLoad in the include file as

Code: Select all

' I am still "xcgui.bi"

Dim Shared _XExitXCGUI As Sub()
_XExitXCGUI = DyLibSymbol(libray, "XExitXCGUI")
Sub XExitXCGUI()
    _XExitXCGUI()
    DyLibFree(library)
End Sub
but
1. fbc says
xcgui.bas(408) error 41: Variable not declared, library in 'DyLibFree(library)'
2. in fact, XExitXCGUI are not be guaranteed to be executed in my app code, which has a common structure like this:

Code: Select all

' I am app
#include "xcgui.bi"

bOk = XInitXCGUI("")

If bOk Then
    do something    
    XExitXCGUI()  
As we may find, if XInitXCGUI can't be called successful, XExitXCGUI can't be called, thus DyLibFree can't be called too.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: question on call functions in DLL

Post by fxm »

oyster wrote:currently I try to wrap the DylibLoad in the include file as

Code: Select all

' I am still "xcgui.bi"

Dim Shared _XExitXCGUI As Sub()
_XExitXCGUI = DyLibSymbol(libray, "XExitXCGUI")
Sub XExitXCGUI()
    _XExitXCGUI()
    DyLibFree(library)
End Sub
but
1. fbc says
xcgui.bas(408) error 41: Variable not declared, library in 'DyLibFree(library)'
If 'library' is previously declared 'Shared', the compilation should be right.
oyster
Posts: 274
Joined: Oct 11, 2005 10:46

Re: question on call functions in DLL

Post by oyster »

blush

there is both libray and library in my code, the first one is a typo
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: question on call functions in DLL

Post by fxm »

The advantage (for memory quota) of using a shared library dynamically is to load/unload it while the program is running.
If you load it at program startup and unload it at the end of the program, use the same shared library (DLL) but statically (with '#inclib'), that is simpler for calling its procedures.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: question on call functions in DLL

Post by D.J.Peters »

Where do you get XCGUI.dll ?

for this link I need an account !
http://git.oschina.net/CodyGuo/xcgui/ra ... /XCGUI.dll

Looks like it's for AutoHotkey and used Unicode but i'm not sure I can not read Chinese :-)

How ever you can use the module constructor and destructor for automatic loading and freeing the library.

Joshy

Code: Select all

' file: "xcgui.bi"
Dim shared As Any Ptr hLibrary
Dim shared as sub () _XExitXCGUI
' ...

' in a *.bas file
#include "xcgui.bi"
sub _init constructor
  hLibrary = DylibLoad("xcgui")
  if hLibrary then
    _XExitXCGUI = DyLibSymbol(hLibrary, "XExitXCGUI")
    if _XExitXCGUI=0 then
      print "error: can't lresolve: 'XExitXCGUI' ! "
      DyLibFree(hLibrary) : hLibrary=0
    end if  
    ' ...
  end if  
end sub

sub _exit destructor
  if hLibrary then
    _XExitXCGUI()
    DyLibFree(hLibrary)
  end if  
end sub
Boris the Old
Posts: 139
Joined: Feb 04, 2011 20:34
Location: Ontario, Canada

Re: question on call functions in DLL

Post by Boris the Old »

fxm wrote:If you load it at program startup and unload it at the end of the program, use the same shared library (DLL) but statically (with '#inclib'), that is simpler for calling its procedures.
In what way is it simpler? Surely the DLL procedures still need to be declared?

Thanks
Rod
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: question on call functions in DLL

Post by fxm »

In static use, you do not have to declare and initialize a procedure pointer (so an additional variable) for each library procedure you want to use. You have just to declare the library procedure names themselves.
Boris the Old
Posts: 139
Joined: Feb 04, 2011 20:34
Location: Ontario, Canada

Re: question on call functions in DLL

Post by Boris the Old »

fxm wrote:You have just to declare the library procedure names themselves.
As you say, it's a lot more simple. Thanks.

Rod
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: question on call functions in DLL

Post by D.J.Peters »

@oyster you don't know me but PLEASE trust me and forget XCGUI and sorry about my bad written English.

The good news I got it running with FreeBASIC.

Code: Select all

#include once "xcgui.bi"

sub XCGUI_init constructor
  XInitXCGUI()
end sub

sub XCGUI_exit destructor 
  XExitXCGUI()
end sub

dim shared as HWINDOW hWindow=NULL

function My_EventBtnClick(pbHandled as BOOL ptr) as integer
  MessageBox(XWnd_GetHWND(hWindow),"was called !","My_EventBtnClick",MB_OK)
  *pbHandled=TRUE
  return 0
end function

dim as wstring ptr pTitle = callocate( len("caption") * Len(WString) )
*pTitle = "caption"
hWindow = XWnd_Create(0,0,300,200,pTitle,,xc_window_style_caption or xc_window_style_allow_maxWindow)
if (hWindow) then
  dim as wstring ptr pLabel = callocate( len("OK") * Len(WString) )
  *pLabel = "OK"
  dim as HELE hButton = XBtn_Create(20,60,80,25,pLabel,hWindow)
  XEle_RegEventC(hButton,XE_BNCLICK, @My_EventBtnClick)
  XWnd_ShowWindow(hWindow,SW_SHOW)
  XRunXCGUI()
  deallocate pLabel
end if    
deallocate pTitle
The bad news:
XCGUI is 32 bit only
XCGUI is a mix of Windows API and and XCGUI a Windows API wrapper.
Tha means to use XCGUI you must learn the Windows API before and than XCGUI too.
But if you learned the Windows API you don't need XCGUI any more (You know what i'm mean ?)

Take a look at the short example I posted:
You have to allocate and free all strings by your self
dim as wstring ptr pTitle = callocate( len("caption") * Len(WString) )
*pTitle = "caption"
use it and than don't forget to free the string
deallocate pTitle

you can't write:
var win = XWnd_Create(0,0,300,200,"I'm the window Title")

FreeBASIC isn't UNICODE ready it supports WString but you can't write
dim as WString title = "Hello world !"
XWnd_Create(0,0,300,200, title)

If you will use XCGUI you must allocate UNICODE strings for all controls and all items also.
Imagine a TreeView with 50 items all items used UNICODE strings :-(

Here are the near same program a Window and a button (unicode/BStr ready)
it used libWindow9 a Windows 32 and 64 bit wrapper

Code: Select all

#Include "window9.bi"
var win = OpenWindow("What a shiny Window :-)",300,10,100,100)
ButtonGadget(1,10,10,60,30,"click me) 
Do
 var event=WaitEvent()
 If event=EventClose Then End
 If event=eventgadget Then MessBox("do it again","Button pressed")
Loop 
And here near the same used fltk-c a Windows and Linux 32/64 bit FLTK C++ wrapper with UTF-8 support
(runs on ARM6 devices Raspberry Pi, BeagleBone black also)

Code: Select all

#include once "fltk-c.bi"
sub ButtonClick cdecl (byval button as FL_WIDGET ptr, byval arg as any ptr)
  Fl_WidgetCopyLabel(button,"do it again") : beep
end sub
var Win = Fl_WindowNew(320,200, "What a shiny Window :-)")
var Btn = Fl_ButtonNew(10,10,120,32, "click me")
Fl_WidgetSetCallback(Btn,@ButtonClick)
Fl_WidgetSize(btn,100,100)
Fl_WindowShow(Win)
Fl_Run()
Compare the size of the three examples XCGUI vs. libWindows9 and fltk-c

Don't invest time in XCGUI it's crap believe it or not but live time is short that is true.

Joshy
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: question on call functions in DLL

Post by D.J.Peters »

Take a look at this code I used WStr()

Code: Select all

#include once "xcgui.bi"
sub XCGUI_init constructor
  XInitXCGUI()
end sub
sub XCGUI_exit destructor 
  XExitXCGUI()
end sub

dim shared as HWINDOW hWindow=NULL
function My_EventBtnClick(pbHandled as BOOL ptr) as integer
  MessageBox(XWnd_GetHWND(hWindow),"was called !","My_EventBtnClick",MB_OK)
  *pbHandled=TRUE
  return 0
end function
var pTitle = strptr(WStr("I'm a window title"))
hWindow = XWnd_Create(0,0,300,200,cptr(wchar_t ptr,pTitle))
if (hWindow) then
  var pLabel = strptr(WStr("Unicode 'Hello World'"))
  dim as HELE hButton = XBtn_Create(20,60,180,25,cptr(wchar_t ptr,pLabel),hWindow)
  XEle_RegEventC(hButton,XE_BNCLICK, @My_EventBtnClick)
  XWnd_ShowWindow(hWindow,SW_SHOW)
  XRunXCGUI()
end if 
Here are the result:
Where are the close button ?
Where are the window title ?
Oh my god the button label looks so great !
Image
XWnd_Create used as style "xc_window_style_default"

and xc_window_style_default are defined as:

Code: Select all

enum xc_window_style_   
	xc_window_style_nothing         = &H00000000
	xc_window_style_caption         = &H00000001
	xc_window_style_border          = &H00000002
	xc_window_style_center          = &H00000004
	xc_window_style_drag_border     = &H00000008
	xc_window_style_drag_window     = &H00000010
	xc_window_style_allow_maxWindow = &H00000020
	xc_window_style_default  = (xc_window_style_caption or xc_window_style_border or xc_window_style_center or xc_window_style_drag_border or xc_window_style_allow_maxWindow)
	xc_window_style_default2 = (xc_window_style_caption or xc_window_style_border or xc_window_style_drag_border or xc_window_style_allow_maxWindow)
	xc_window_style_modal    = (xc_window_style_caption or xc_window_style_center or  xc_window_style_border)
end enum
So it's use xc_window_style_caption but no caption are shown ...

Joshy
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: question on call functions in DLL

Post by D.J.Peters »

Ups may be I`m wrong and i'm more confuse as before :-(

I created a macro _L()

#define _L(txt) cptr(wchar_t ptr,strptr(WStr(txt)))

Using string literals (at compile time)

It looks near the same as I saw in a help file.

Code: Select all

#include once "xcgui.bi"
sub InitXCGUI constructor
  XInitXCGUI()
end sub
sub ExitXCGUI destructor 
  XExitXCGUI()
end sub

function ButtonCB(pbHandled as BOOL ptr) as integer
  MessageBox(NULL,"do it again!","ButtonCB",MB_OK)
  *pbHandled=true
  return 0
end function

var xWin = XWnd_Create(0,0,300,200,_L("I'm a window title"))
if (xWin) then
  var xButton = XBtn_Create(20,60,180,25,_L("Hello World!"),xWin)
  XEle_RegEventC(xButton, XE_BNCLICK, @ButtonCB)
  XWnd_ShowWindow(xWin, SW_SHOW)
  XRunXCGUI()
end if 
Image
You can see the example from help defines a window title but the result does not show the title seams to be normal not crap at all !

There are more pictures in the help file all source codes define a window title but they are never shown.
No close box or mini or maximize button's on top of any window.

Does it makes any sense for you ?

Window titles in China bring misfortune :lol:

Joshy
oyster
Posts: 274
Joined: Oct 11, 2005 10:46

Re: question on call functions in DLL

Post by oyster »

Thanks, every one

I put xcgui.dll, which is a 32bits dll and said to be free for use, here https://github.com/retsyo/xcgui_nim (btw you can find that I am stuck in this nim binding)

In fact, there is an incompleted binding for VB over the internet, it is not hard to make it go with fb's syntax. here is what I get

Code: Select all

#include "windows.bi"
#inclib "xcgui"

Type HWINDOW As Integer
Type HXCGUI As Integer
Type HELE As Integer

Declare Function XInitXCGUI Cdecl Lib "xcgui" Alias "XInitXCGUI" (ByVal pText As LPCWSTR = NULL) As Boolean

Declare Function XWnd_Create Cdecl Lib "xcgui" Alias "XWnd_Create" (ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal pTitle As LPCWSTR, ByVal hWndParent As HWND = NULL, ByVal XCStyle As Integer = 5) As HWINDOW

Declare Function XWnd_ShowWindow Cdecl Lib "xcgui" Alias "XWnd_ShowWindow"(ByVal hWindow As Integer, ByVal nCmdShow As Integer) As Boolean

Declare Sub XRunXCGUI Cdecl Lib "xcgui" Alias "XRunXCGUI"()

Declare Sub XExitXCGUI Cdecl Lib "xcgui" Alias "XExitXCGUI"()

Declare Function XShapeText_Create Cdecl Lib "xcgui" Alias "XShapeText_Create" (ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal pName As LPCWSTR, ByVal hParent As HXCGUI = NULL) As HXCGUI

Declare Function XBtn_Create Cdecl Lib "xcgui"  Alias "XBtn_Create"  (ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal pName As LPCWSTR, ByVal hParent As Integer) As Integer


Function OnClick(ByRef bHandle As Integer) As Integer
    Dim as Integer res
    ' ~ res = XC_MessageBox(0, "ok", "title", 1)
    print "in OnClick"
    bHandle = True
    OnClick = 0
End Function

dim as Boolean bOk
dim as HWINDOW hWindow
dim as HELE hBtn

bOk = XInitXCGUI(0)

If bOk Then
    hWindow = XWnd_Create(0, 0, 300, 200, ("demo"), 0, 5)
    print cast(Integer, hWindow)

    XShapeText_Create(18, 2, 100, 50, "add caption bar", hWindow)

    hBtn = XBtn_Create( 8, 30, 100, 20, "click me", hWindow )
    ' ~ bTmp = XEle_RegEventC(hBtn, XE_BNCLICK, cast(Integer, @OnClick))

    If hWindow <> 0 Then
        XWnd_ShowWindow( hWindow, 5 )  Rem invalid handle?
        XRunXCGUI()
    End If

    XExitXCGUI()

End If
```

which can be compiled but when I run, it crashes and says "API: XND_ShowWindow(), invalid handle(0x2)"
btw, the caption bar is created by XShapeText_Create

Since this VB-binding is not completed and this binding method does not work( ok, maybe my fault which I have not known), I use Python( and mankind) to convert the xcgui.h to what I wrote in the beginning

ps, sorry mostly I use python because it supplies short syntax to handle string which is what I hate in BASIC(left, mid, right...). And there is no "for each" in Freebasic.

As for xcgui, 
Advantage: it can load skin to change and make beautiful theme. it can make irregular window.
Disadvantage: only 32 bits is free, the 64 bits dll, the layout designer and the static lib are commercial software. There is no editable microsoft Excel-like grid cell contols) which I need. Maybe I have to relearn wx-c for freebasic again
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: question on call functions in DLL

Post by D.J.Peters »

@oyster before I show all the details, what goes wrong with your code do you use XCGUI v1.9.9 from Oct 2017 ?

This is what I use here:
Image

Give me a link to the version do you use !

I got it they put buttons manually on the titlebar and don't use the buttons from Window manager :-)

Joshy

Code: Select all

#include once "xcgui.bi"
sub InitXCGUI constructor
  XInitXCGUI()
end sub
sub ExitXCGUI destructor 
  XExitXCGUI()
end sub

function ButtonCB(pbHandled as BOOL ptr) as integer
  print "ButtonCB"
  *pbHandled=true
  return 1
end function

var xWin = XWnd_Create(0,0,300,200,_L("Im a window title"))
if (xWin) then
  XBtn_SetType(XBtn_Create(300-23,3,20,20,_L("X"),xWin),button_type_close)
  XShapeText_Create(18, 2, 100, 50, _L("add caption bar"), xWin)
  var xButton = XBtn_Create(20,60,180,25,_L("Hello World!"),xWin)
  XEle_RegEventC(xButton, XE_BNCLICK, @ButtonCB)
  XWnd_ShowWindow(xWin, SW_SHOW)
  XRunXCGUI()
else
  print "error: XWnd_Create()) !"
  beep : sleep 
end if
Image
Post Reply