Jump to content

FreeBASIC example plugin


Uten
 Share

Recommended Posts

EDIT2: Just skip this part and go stright for the good stuff made by @bastel123 (post 6) :lmao:

EDIT: Thanks to @bastel123 this "framework" now works with FreeBASIC 0.17b. That is I still have cheated by compilling the helper functions as a static library with dev-cpp. @bastel123 has also provided his code hand a dll to prove it works. I'm however not able to compile his code yet, to many errors witch is strange as he obviously are able to generate a dll from his code.

---

So consider this work in progress (or probably stalled work, depending on

time and interest :ph34r: )

Most of the work done in these files can be found at the FreeBasic Forum.

I have collected it and tried to make it work without much success.

Probably something wrong with the way AU3_GetPluginDetails is implemented.

I'm just posting this to see if it will catch any interest and possibly get pointers

on where this code goes wrong.

As of now I have created a static library of AU3_Plugin_SDK\au3plugin.c (with

dev-cpp) and placed it in my freebasic\lib folder and called it libAutoItPlugInSDK.a.

I have also tried to make this with FreeBASIC only code but without implementing

the private methods in au3plugin.c

I'm compiling the file exaqmpleFreeBasic.bas with the following command-line:

fbc -export -dll exampleFreeBasic.bas

FILE: au3plugin.bi coresponds to au3plugin.h

CODE
#ifndef __AU3PLUGIN_H

#define __AU3PLUGIN_H

'' RESOURCE: http://www.freebasic.net/forum/viewtopic.php?t=3897

'' freebasic translation of Jonathan Bennett's AutoIt SDK au3plugin.h

''

'' Includes

#include "windows.bi"

'' TODO: I have created a static library of the au3plugin.c and au3plugin.h

'' To remove the static library au3plugin.c has to be translated.

'' The simplest possible implementation is found at the bottom of this file

#inclib "AutoItPlugInSDK"

'' Defines

'' (Parker-) you don't really need this, since it is changed below to "EXPORT".

''#define AU3_PLUGINAPI __declspec(dllexport)

#define AU3_PLUGINAPI export

#define NULL 0

#define AU3_PLUGIN_OK 0

#define AU3_PLUGIN_ERR 1

#define AU3_PLUGIN_INT32 1

#define AU3_PLUGIN_INT64 2

#define AU3_PLUGIN_DOUBLE 3

#define AU3_PLUGIN_STRING 4

#define AU3_PLUGIN_HWND 5

#define AU3_PLUGIN_ITOA_MAX 65

'' Variant and plugin function structures

Type AU3_PLUGIN_VAR As tagAU3_PLUGIN_VAR

Type tagAU3_PLUGIN_VAR

m_nType As Integer '' Type

Union

m_nValue As Integer '' Value of int32 (for AU3_PLUGIN_INT32)

m_n64Value As Longint '' Value of int64 (for AU3_PLUGIN_INT64)

m_fValue As Double '' Value of double (for AU3_PLUGIN_DOUBLE)

m_szValue As Zstring Ptr '' Value of double (for AU3_PLUGIN_STRING)

m_hWnd As HWND '' Value of handle (for AU3_PLUGIN_HWND)

End Union

End Type

Type AU3_PLUGIN_FUNC As tagAU3_PLUGIN_FUNC

Type tagAU3_PLUGIN_FUNC

m_szName As Zstring Ptr

m_nMinParams As Integer

m_nMaxParams As Integer

End Type

'' Simplified function declarations

'' TODO: I'm not able to use this macro in freebasic. I'm writing everything by hand.

#define AU3_PLUGIN_DEFINE(funcname) Function funcname(Byval n_AU3_NumParams As Integer, Byval p_AU3_Params As AU3_PLUGIN_VAR Ptr, Byval p_AU3_Result As AU3_PLUGIN_VAR Ptr ptr, Byval n_AU3_ErrorCode As Integer Ptr, Byval n_AU3_ExtCode As Integer Ptr) As Integer export

''/* Helper functions For working With variant like variables */

Declare Function AU3_AllocVar( ) As AU3_PLUGIN_VAR Ptr

''Declare Sub AU3_FreeVar(Byval pVar As AU3_PLUGIN_VAR ptr ptr)

Declare Sub AU3_ResetVar(Byval pVar As AU3_PLUGIN_VAR)

Declare Function AU3_GetType(Byval pVar As AU3_PLUGIN_VAR ptr) As Integer

Declare Sub AU3_SetString(Byval pVar As AU3_PLUGIN_VAR ptr, Byval szString As Zstring Ptr)

Declare Function AU3_GetString(Byval pVar As AU3_PLUGIN_VAR ptr) As Zstring Ptr

Declare Sub AU3_FreeString(Byval szString As Zstring Ptr)

Declare Sub AU3_SetInt32(Byval pVar As AU3_PLUGIN_VAR ptr, Byval nValue As Integer)

Declare Function AU3_GetInt32(Byval pVar As AU3_PLUGIN_VAR ptr) As Integer

Declare Sub AU3_SetInt64(Byval pVar As AU3_PLUGIN_VAR ptr, Byval n64value As Longint)

Declare Function AU3_GetInt64(Byval pVar As AU3_PLUGIN_VAR ptr) As Longint

Declare Sub AU3_SetDouble(Byval pVar As AU3_PLUGIN_VAR ptr, Byval fValue As Double)

Declare Function AU3_GetDouble(Byval pVar As AU3_PLUGIN_VAR ptr) As Double

Declare Sub AU3_SethWnd(Byval pVar As AU3_PLUGIN_VAR ptr, Byval hWnd As HWND)

Declare Function AU3_GethWnd(Byval pVar As AU3_PLUGIN_VAR ptr) As HWND

Declare Function AU3_HexToDec(Byval szHex As Zstring Ptr) As Integer

'' END

#endif

FILENAME: exampleFreeBasic.bas coresponds to example.c

CODE
#include "au3plugin.bi"

#include "windows.bi"

'' RESOURCE: http://www.freebasic.net/forum/viewtopic.p...ighlight=autoit

'' freebasic translation of example.c

''

'' TODO: Looks like AU3_GetPluginDetails does not return the correct information

'''Dim plug1 as zstring ptr

'''*plug1= "PluginMsgBox"

'''Dim plug2 as zstring ptr

'''*plug2 = "PluginAdd"

'''Dim g_AU3_Funcs (0 to 1) As AU3_PLUGIN_FUNC => { (plug1, 0, 0), (plug2, 1, 1) }

'''

'''Function AU3_GetPluginDetails CDECL Alias "AU3_GetPluginDetails" (ByVal n_AU3_NumFuncs as integer

'''ptr, ByVal p_AU3_Func as AU3_PLUGIN_FUNC Ptr ptr) As Integer export''AU3_PLUGINAPI

''' '' Pass back the number of functions that this DLL supports

''' n_AU3_NumFuncs = sizeof(g_AU3_Funcs)/sizeof(AU3_PLUGIN_FUNC)

'''

''' '' Pack back the address of the global function table

''' p_AU3_Func = g_AU3_Funcs

'''

''' Return AU3_PLUGIN_OK

'''End Function

''' Chenged to the way bastel123 has done it.

dim shared g_AU3_Funcs(1) as AU3_PLUGIN_FUNC

g_AU3_Funcs(0).m_szName=strptr("PluginAdd")

g_AU3_Funcs(0).m_nMinParams=2

g_AU3_Funcs(0).m_nMaxParams=2

g_AU3_Funcs(1).m_szName=strptr("PluginMessageBox")

g_AU3_Funcs(1).m_nMinParams=2

g_AU3_Funcs(1).m_nMaxParams=2

function AU3_GetPluginDetails cdecl alias "AU3_GetPluginDetails" _

(byref n_AU3_NumFuncs as integer, _

byref p_AU3_Func as AU3_PLUGIN_FUNC ptr) as integer export

'/* Pass back the number of functions that this DLL supports */

n_AU3_NumFuncs = abs((sizeof(g_AU3_Funcs)*(ubound(g_AU3_Funcs)-lbound(g_AU3_Funcs)))/sizeof(AU3_PLUGIN_FUNC))+1

' /* Pack back the address of the global function table */

p_AU3_Func = @g_AU3_Funcs(0)

return AU3_PLUGIN_OK

end function

'' NOTE: fbc creates DllMain: SOURCE: http://www.freebasic.net/forum/viewtopic.p...ghlight=dllmain

'' mhookdll.bas

'' AU3_PLUGIN_DEFINE: Simplified function macro

Public Function PluginMsgBox CDECL Alias "PluginMsgBox" (Byval n_AU3_NumParams As Integer, Byval p_AU3_Params As AU3_PLUGIN_VAR Ptr, Byval p_AU3_Result As AU3_PLUGIN_VAR Ptr ptr, Byval n_AU3_ErrorCode As Integer Ptr, Byval n_AU3_ExtCode As Integer Ptr) As Integer export

'' The inputs to a plugin function are:

'' n_AU3_NumParams - The number of parameters being passed

'' p_AU3_Params - An array of variant like variables used by AutoIt

''

'' The outputs of a plugin function are:

'' p_AU3_Result - A pointer to a variant variable for the result

'' n_AU3_ErrorCode - The value for @Error

'' n_AU3_ExtCode - The value for @Extended

''

Dim zs As Zstring * 20

Dim ws As Wstring * 20

zs = "Hello World"

ws = Wstr(zs)

MessageBox(null, ws, Wstr("Unicode 'Hello World'"), MB_OK Or MB_ICONINFORMATION)

Return AU3_PLUGIN_OK

End Function

'' AU3_PLUGIN_DEFINE(PluginAdd)

Public Function PluginAdd CDECL Alias "PluginAdd" (Byval n_AU3_NumParams As Integer, Byval p_AU3_Params As AU3_PLUGIN_VAR Ptr, Byval p_AU3_Result As AU3_PLUGIN_VAR Ptr ptr, Byval n_AU3_ErrorCode As Integer Ptr, Byval n_AU3_ExtCode As Integer Ptr) As Integer export

''funcname(int n_AU3_NumParams, const AU3_PLUGIN_VAR *p_AU3_Params, AU3_PLUGIN_VAR **p_AU3_Result, int *n_AU3_ErrorCode, int *n_AU3_ExtCode)

Dim pMyResult As AU3_PLUGIN_VAR ptr

''/* Allocate the return variable */

Dim nResult As Integer

nResult = 30

''AU3_SetInt32(pMyResult, nResult)

''/* Pass back the result, error code and extended code.

'' * Note: AutoIt is responsible for freeing the memory used in p_AU3_Result

''*/

p_AU3_Result = 30

n_AU3_ErrorCode = 0

n_AU3_ExtCode = 0

Return AU3_PLUGIN_OK

End Function

/'

Public Sub AU3_FreeVar cdecl Alias "AU3_FreeVar" (Byval pVar as AU3_PLUGIN_VAR ptr ptr) export

''AU3_ResetVar(pVar)

Deallocate(pVar)

End Sub

Sub AU3_ResetVar(Byval pVar as AU3_PLUGIN_VAR ptr ptr)

if pVar.m_nType = AU3_PLUGIN_STRING Then

Deallocate(pVar.m_szValue);

pVar.m_nType = AU3_PLUGIN_INT32;

pVar.m_nValue = 0;

End Sub

'/

FILENAME:

; File prepared to use a freebasic implementation of AU3_Plugin_SDK
; NOTE: As of writing (21 oct 2006) exampleFreeBasic.dll does not work! It does not export it's methode names as expected.
#Region Compiler directives section
#compiler_compression = 4
#compiler_OutFile_Type=a3x         ;a3x
;#compiler_run_after=move %out% c:\ ;TODO: Put it somewhere
#compiler_run_after=del /F %out%    ;TODO: Or delete it?
#compiler_plugin_funcs=PluginAdd, PluginMsgBox
#endregion

Local $pluginPathName = "exampleFreeBasic.dll"
If FileExists($pluginPathName) Then 
   $handle = PluginOpen($pluginPathName)
   ConsoleWrite("$handle:=" & $handle & @LF)
Else 
   MsgBox(16, "ERROR:", "Could not locate file: " & $pluginPathName & ", Terminating")
   Exit
EndIf 
;PluginMsgBox("My title", "My text")
$retval = PluginAdd(10, 50) 
msgbox(0, "PluginAdd 10, 50", "Return value: " & $retval & "    @error: " & @error & "    @extended: " & @extended)

$retval = PluginAdd("10", "50") 
msgbox(0, "PluginAdd ""10, 50""", "Return value: " & $retval & "    @error: " & @error & "    @extended: " & @extended)
Exit

Func OnAutoItExit()
   PluginClose($handle)
   Exit
EndFunc

EDIT: Why does this page render like crap? Placed hard line brakes in text.

EDIT2: Changed the code for AU3_GetPluginDetails according to the sample provided by bastel123. Now I can compile it and get AutoIt recognize the new functions.

Edited by Uten
Link to comment
Share on other sites

So consider this work in progress (or probably stalled work, depending on time and interest :ph34r: )

I hope it wont stall, would be nice to have :geek:

i'm not good at c but i will take a look at it when i have more time.

4 eyes see more than 2 :)

but dont expect (too) much :lmao:

CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map
Link to comment
Share on other sites

Hi again @bastel123,

Thanks for sharing this with us :whistle:

Unfortunately I'm not able to compile your code directly. But changing my code for AU3_GetPluginDetails to your implementation did the trick on my side. I have not analyzed the output from your code, as I got my own to work, but if you have any ideas I would like to here them.

To compile your code I have used FreeBASIC 0.17b with the command:

fbc -export -dll example.bas

Do you do it any other way?

This is the output I got:

G:\codeX\freebasic\au3plugins\plugin_src>fbc -export -dll example.bas
example.bas(49) : error 18: Syntax error, found: 'PluginMessageBox'

AU3_PLUGIN_DEFINE(PluginMessageBox)
                                   ^
example.bas(74) : warning level 0: Implicit variable allocation, p_AU3_Params
example.bas(74) : error 30: Expected pointer, before: ')'

        szTitle = AU3_GetString(@p_AU3_Params[0])
                                                ^
example.bas(74) : warning level 0: Passing different pointer types, at parameter
 1 (pVar) of AU3_GETSTRING()
example.bas(75) : error 30: Expected pointer, before: ')'

        szText  = AU3_GetString(@p_AU3_Params[1])
                                                ^
example.bas(75) : warning level 0: Passing different pointer types, at parameter
 1 (pVar) of AU3_GETSTRING()
example.bas(94) : error 30: Expected pointer, before: '='

        *p_AU3_Result          = pMyResult
                                ^
example.bas(94) : warning level 0: Implicit conversion
example.bas(95) : error 30: Expected pointer, before: '='

        *n_AU3_ErrorCode        = 0
                                ^
example.bas(96) : error 30: Expected pointer, before: '='

        *n_AU3_ExtCode        = 0
                                ^
example.bas(112) : error 18: Syntax error, found: 'PluginAdd'

AU3_PLUGIN_DEFINE(PluginAdd)
                            ^
example.bas(126) : warning level 0: Implicit variable allocation, p_AU3_Params
example.bas(126) : error 30: Expected pointer, before: ')'

        AU3_SetInt32(pMyResult, AU3_GetInt32(@p_AU3_Params[0])+AU3_GetInt32(@p_A
U3_Params[1]))
                                                             ^
example.bas(126) : warning level 0: Passing different pointer types, at paramete
r 1 (pVar) of AU3_GETINT32()
example.bas(126) : warning level 0: Passing different pointer types, at paramete
r 1 (pVar) of AU3_GETINT32()
example.bas(134) : error 30: Expected pointer, before: '='

        *p_AU3_Result          = pMyResult
                                ^
example.bas(134) : warning level 0: Implicit conversion
example.bas(135) : error 30: Expected pointer, before: '='

        *n_AU3_ErrorCode        = 0
                                ^
example.bas(135) : error 120: Too many errors, exiting

G:\codeX\freebasic\au3plugins\plugin_src>
Link to comment
Share on other sites

Nicely don @bastel123

Thanks a lot :whistle:

If your testing this from SicTe adding compiler directives at the top of the plugintest.au3 file will make life easier.

#Region Compiler directives section
#compiler_compression = 4
#compiler_OutFile_Type=exe         ;a3x
;#compiler_run_after=move %out% c:\temp  ;TODO: Put it somewhere
#compiler_run_after=del /F %out%       ;TODO: Or delete it?
#compiler_plugin_funcs=pluginadd, pluginmessagebox
#endregion
Link to comment
Share on other sites

  • 1 year later...

I realize that this is an old topic but some others may benefit from this.

I just recently created a plugin which needed to return a string. I spent half a day trying to figure out why I could not get the string back in my au3 program. I would just get garbage and a sometimes a crash. I finally tracked the problem down to Au3plugin.bas and more specifically AU3_SetString.

Here's how it is in original form:

sub AU3_SetString (byval pVar as AU3_PLUGIN_VAR ptr, byval szString as zstring ptr)
    AU3_ResetVar(pVar)
    pVar->m_nType = AU3_PLUGIN_STRING
    pVar->m_szValue = allocate( len(szString)+1 )
    pVar->m_szValue=szString
    
end sub

What turns out to be the problem is that this line:

pVar->m_szValue = allocate( len(szString)+1 )

is allocating 5 bytes ( the size of pointer +1 byte) and passing the pointer to pVar->m_szValue.

The next line

pVar->m_szValue=szString
is then replacing the pointer for the allocated memory with the pointer to the string.

This creates two problem, first: unused memory (memory leak?), and secondly the string is never copied.

Well, it creates a third problem too, access violation.

Here's the code from the Au3Plugin.c

void AU3_SetString(AU3_PLUGIN_VAR *pVar, const char *szString)
{
    AU3_ResetVar(pVar);

    pVar->m_nType = AU3_PLUGIN_STRING;
    pVar->m_szValue = (char *)malloc( strlen(szString)+1 );
    strcpy(pVar->m_szValue, szString);
}

What it shows above is that it is allocating the length of the string + 1 byte , passing the pointer to pVar->m_szValue and then copying the string to the new pointer.

Here's the fixed FreeBASIC version:

sub AU3_SetString (byval pVar as AU3_PLUGIN_VAR ptr, byval szString as zstring ptr)
    AU3_ResetVar(pVar)
    pVar->m_nType = AU3_PLUGIN_STRING
    pVar->m_szValue = allocate( Len(*szString)+1 )
    *pVar->m_szValue = *szString
end sub

I should note that I am using FreeBASIC 0.18.3.

If need be, I can upload the corrected SDK.

I have made two small plugins with FreeBASIC now and it works great.

Edited by eltorro
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...