Sign in to follow this  
Followers 0
GreenBox

Autoit DllCallbackRegister have a bug?

2 posts in this topic

#1 ·  Posted (edited)

I'm sorry my english...

i try DllCallbackRegister($func, "ptr:cdecl", "ptr; ptr") but it's raise error when callback called.

only use can DllCallbackRegister($func, "ptr:cdecl", "ptr") but no idea how get param from python...

help please.

output:

E:\Users\EcmaXp\Desktop>python32 ./module1.py
<module 'spam' (built-in)>
['__doc__', '__name__', '__package__', 'hello'
<built-in function hello>
hello
3 <module 'spam' (built-in)>
E:\Users\EcmaXp\Desktop>rem after compile change to DllCallbackRegister($func, "ptr:cdecl", "ptr; ptr")

E:\Users\EcmaXp\Desktop>python32 ./module1.py
<module 'spam' (built-in)>
['__doc__', '__name__', '__package__', 'hello'
<built-in function hello>
E:\Users\EcmaXp\Desktop>rem error!

E:\Users\EcmaXp\Desktop>

code:

; Python 3.1 <=> Autoit 3

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#NoTrayIcon
#include <misc.au3>
#include <string.au3>

Global $_NON_FREE_STRUCT[1]
Global $_current_line = -1
Global $_Py_AutoitDebug = False
Global $_Py_AutoitMaxiumArgmentCount = 4

Global Const $PYTHON_API_VERSION = 1013

Global Const $tagPyObject = _
    "long_ptr ob_refcnt;" & _ ; long_ptr is a ssize_t is a Py_ssize_t
    "ptr ob_type;"

Global Const $tagPyCFunctionObject = _
    $tagPyObject & _ ; PyObject_HEAD
    "ptr m_ml;" & _ ; PyObject /* Description of the C function to call */
    "ptr m_self;" & _ ; PyObject /* Passed as 'self' arg to the C func, can be NULL */
    "ptr m_module;" ; PyObject /* The __module__ attribute, can be anything */

Global Const $tagPyModuleDef_Base = _
    $tagPyObject & _ ; PyObject_HEAD
    "ptr m_init;" & _ ; PyObject* (*m_init)(void)
    "long_ptr m_index;" & _ ; PyObject
    "ptr m_copy;" ; PyObject

Global Const $tagPyModuleDef = _
    $tagPyModuleDef_Base & _ ; PyObject_HEAD
    "ptr m_name;" & _ ; const char*
    "ptr m_doc;" & _ ; const char*
    "long_ptr m_size;" & _ ; Py_ssize_t
    "ptr m_methods;" & _ ; PyMethodDef
    "ptr m_reload;" & _ ; inquiry
    "ptr m_traverse;" & _ ; traverseproc
    "ptr m_clear;" & _ ; inquiry
    "ptr m_free;" ; freefunc

Global Const $tagPyMethodDef = _
    "ptr ml_name;" & _ ; char[] /* The name of the built-in function/method */
    "ptr ml_meth;" & _ ; PyCFunction /* The C function that implements it */
    "int ml_flags;" & _ ; /* Combination of METH_xxx flags, which mostly describe the args expected by the C func */
    "ptr ml_doc;" ; /* The __doc__ attribute, or NULL */

Global Const $Py_NULL = Ptr(0)
Global Const $METH_VARARGS  = 0x0001
Global Const $METH_KEYWORDS = 0x0002
Global Const $METH_NOARGS   = 0x0004
Global Const $METH_O        = 0x0008
Global Const $METH_CLASS    = 0x0010
Global Const $METH_STATIC   = 0x0020
Global Const $METH_COEXIST  = 0x0040

Func PyAu_MakePyMethodDef($funcname, $pycfunction, $doc="");, $flag=$METH_VARARGS, $doc="")
    $assign_data = True

    If Not StringLen($funcname) And Not StringLen($pycfunction) Then
        $assign_data = False
    EndIf

    If $assign_data Then
        #cs
        $callbackarg = ""

        If BitAnd($flag, $METH_VARARGS) Then
            $callbackarg = "ptr; ptr"
        EndIf

        If BitAnd($flag, $METH_KEYWORDS) Then
            $callbackarg = "ptr; ptr; ptr;"
        EndIf

        If BitAnd($flag, $METH_NOARGS) Then
            $callbackarg = "ptr; ptr; ptr;"
        EndIf
        #ce

        $flag = $METH_VARARGS
        $callbackfunc = DllCallbackRegister($pycfunction, "ptr:cdecl", "ptr") ; THIS LINE
        ; I went get two param but Autoit raise error!
        ; how can i work?
    EndIf

    $pymethod = DllStructCreate($tagPyMethodDef)

    If $assign_data Then
        DllStructSetData($pymethod, "ml_name", MakeStringBuffer($funcname))
        DllStructSetData($pymethod, "ml_meth", DllCallbackGetPtr($callbackfunc))
        DllStructSetData($pymethod, "ml_flags", $flag)
        DllStructSetData($pymethod, "ml_doc", _Iif(StringLen($doc), MakeUnicodeBuffer($doc), $Py_NULL))
    EndIf

    NonFreeStruct($pymethod)

    Return $pymethod
EndFunc

#cs
Func PyAu_MakeCFunctionObject($func, $self=$Py_NULL, $module=$Py_NULL)
    $pycfunctionobj = DllStructCreate($tagPyCFunctionObject)
    DllStructSetData($pycfunctionobj, "m_ml", DllCallbackGetPtr($callbackfunc))
    DllStructSetData($pycfunctionobj, "m_self", $self)
    DllStructSetData($pycfunctionobj, "m_module", $module)
    NonFreeStruct($pycfunctionobj)

    Return DllStructGetPtr($pycfunctionobj)
EndFunc
#ce

#Region user code
$PyDLL = DllOpen("python31")

Func TestFunction($mod, $args)
    print("hello")
    Return $mod

    #cs
    $result = PyArg_ParseTuple($args, "ii", "int", "int")
    If Not IsArray($result) Then Return

    print("called testfuncion!")
    Return Py_BuildValue("i", "int", $result[1] + $result[2])
    #ce
EndFunc

Func PyInit_spam()
    $a = PyAu_MakePyMethodDef("hello", "TestFunction")
    $b = PyAu_MakePyMethodDef("", "")
    $pymethods = ConcatStruct($a, $b)

    $pymodule = DllStructCreate($tagPyModuleDef)
    DllStructSetData($pymodule, "m_name", MakeStringBuffer("spam"))
    DllStructSetData($pymodule, "m_size", -1)
    DllStructSetData($pymodule, "m_methods", GetFreezeStructPtr($pymethods))

    Return PyModule_Create(GetFreezeStructPtr($pymodule))
EndFunc

$initfunc = DllCallbackRegister("PyInit_spam", "ptr", "")

Py("Import_AppendInittab", "none", "ptr", MakeStringBuffer("spam"), "ptr", DllCallbackGetPtr($initfunc))

Py_Initialize()
Global Const $Py_None = Py_GetNone()
Py_Main()
Py_Finalize()
#EndRegion user code

#Region python functions
Func Py_Initialize()
    Py("_Initialize", "none")
EndFunc   ;==>Py_Initialize

Func Py_GetNone()
    Local Static $Py_None = -1
    If $Py_None == -1 Then
        $module = PyImport_ImportModule("builtins")
        $moduledict = PyModule_GetDict($module)
        $Py_None = PyDict_GetItem($moduledict, Py_BuildString("None"))
    EndIf

    Py_INCREF($Py_None)
    Return $Py_None
EndFunc

Func PyImport_ImportModule($name)
    Return Py("Import_ImportModule", "ptr", "ptr", MakeStringBuffer(String($name)))
EndFunc

Func Py_IsInitialized()
    Return Py("_IsInitialized", "int")
EndFunc   ;==>Py_IsInitialized

Func Py_Finalize()
    Return Py("_Finalize", "none")
EndFunc   ;==>Py_Finalize

Func Py_Module_New($name)
    Return Py("Module_New", "ptr", "ptr", MakeStringBuffer(String($name)))
EndFunc   ;==>Py_Module_New

Func PyModule_GetDict($module)
    Return Py("Module_GetDict", "ptr", "ptr", $module)
EndFunc   ;==>PyModule_GetDict

Func Py_BuildString($string)
    Return Py_BuildValue("s", "ptr", MakeStringBuffer($string))
EndFunc   ;==>Py_BuildString

Func PyImport_GetModuleDict()
    Return Py("Import_GetModuleDict", "ptr")
EndFunc   ;==>PyImport_GetModuleDict

Func PyDict_SetItem($dict, $key, $value)
    Return Py("Dict_SetItem", "int", "ptr", $dict, "ptr", $key, "ptr", $value)
EndFunc   ;==>PyDict_SetItem

Func PyDict_GetItem($dict, $key)
    Return Py("Dict_GetItem", "ptr", "ptr", $dict, "ptr", $key)
EndFunc   ;==>PyDict_SetItem

Func PyModule_Create($module)
    Return PyModule_Create2($module, $PYTHON_API_VERSION)
EndFunc

Func PyModule_Create2($moduledef, $apiver)
    Return Py("Module_Create2", "ptr", "ptr", $moduledef, "int", $apiver)
EndFunc

Func Py_INCREF($objptr)
    $obj = DllStructCreate($tagPyObject, $objptr)
    DllStructSetData($obj, "ob_refcnt", DllStructGetData($obj, "ob_refcnt") + 1)

    If $_Py_AutoitDebug Then
        print("current(irc) : " & DllStructGetData($obj, "ob_refcnt"))
    EndIf
EndFunc   ;==>Py_INCREF

Func Py_DECREF($objptr)
    $obj = DllStructCreate($tagPyObject, $objptr)
    DllStructSetData($obj, "ob_refcnt", DllStructGetData($obj, "ob_refcnt") - 1)

    If $_Py_AutoitDebug Then
        print("current(dec) : " & DllStructGetData($obj, "ob_refcnt"))
    EndIf
EndFunc   ;==>Py_DECREF

Func Py_BuildValue($valueformat, _
        $T1 = "", $P1 = "", _
        $T2 = "", $P2 = "", _
        $T3 = "", $P3 = "", _
        $T4 = "", $P4 = "", _
        $line = @ScriptLineNumber)

    If Not Mod(@NumParams, 2) Then
        _Py_AutoitInteralError("Wrong Argment Given")
        Return
    EndIf

    $paramtempformat = ""

    For $i = 1 To Int(@NumParams / 2)
        $paramformat = Eval("T" & $i)
        $param = Eval("P" & $i)

        $paramtempformat &= $paramformat & ";"
    Next

    $va_list = DllStructCreate($paramtempformat)

    For $i = 1 To Int(@NumParams / 2)
        $param = Eval("P" & $i)
        DllStructSetData($va_list, $i, $param)
    Next

    $result = Py("_VaBuildValue", "ptr", "str", $valueformat, "ptr", DllStructGetPtr($va_list))
    $va_list = 0

    Return $result
EndFunc   ;==>Py_BuildValue

Func PyArg_ParseTuple($valueformat, _
        $T1 = "", _
        $T2 = "", _
        $T3 = "", _
        $T4 = "", _
        $line = @ScriptLineNumber)

    For $i = 1 to $_Py_AutoitMaxiumArgmentCount
        If Not IsDeclared("T" & $i) Then
            If @NumParams > ($i + 1)  Then
                _Py_AutoitInteralError("Wrong Argment Given")
                Return
            EndIf
        EndIf
    Next

    Local $resultvalue[@NumParams]
    $resultvalue[0] = @NumParams - 1

    $paramtempformat = ""

    For $i = 1 To $resultvalue[0]
        $paramformat = Eval("T" & $i)
        $paramtempformat &= $paramformat & ";"
    Next

    $va_list = DllStructCreate($paramtempformat)

    $result = Py("Arg_VaParse", "int", "str", $valueformat, "ptr", DllStructGetPtr($va_list))
    If Not $result Then
        Return False
    EndIf

    $va_list = 0

    For $i = 1 To $resultvalue[0]
        $param = Eval("P" & $i)
        $resultvalue[$i] = DllStructGetData($va_list, $i)
    Next

    Return $resultvalue
EndFunc

Func Py_Main()
    $argc = $CmdLine[0] + 1
    $argv = DllStructCreate(StringTrimRight(_StringRepeat("ptr;", $argc), 1))

    DllStructSetData($argv, 1, MakeUnicodeBuffer(@ScriptFullPath))

    For $i = 2 To $argc
        DllStructSetData($argv, $i, MakeUnicodeBuffer($CmdLine[$i - 1]))
    Next

    Py("_Main", "none", "int", $argc, "ptr", DllStructGetPtr($argv))

    $argv = 0
EndFunc   ;==>Py_Main
#EndRegion python functions

#Region help functions
Func print($arg)
    ConsoleWrite($arg & @CRLF)
EndFunc   ;==>print

Func NonFreeStruct(ByRef $x)
    Global $_NON_FREE_STRUCT
    $size = UBound($_NON_FREE_STRUCT)
    ReDim $_NON_FREE_STRUCT[$size + 1]
    $_NON_FREE_STRUCT[$size] = $x
EndFunc   ;==>NonFreeStruct

Func CleanLastStruct($number = 1)
    Global $_NON_FREE_STRUCT
    $size = UBound($_NON_FREE_STRUCT)
    For $i = 1 To $number
        $_NON_FREE_STRUCT[$size] = 0
        ReDim $_NON_FREE_STRUCT[$size - 1]
        $size -= 1
    Next
EndFunc   ;==>CleanLastStruct

Func GetStructAsByte($a)
    $tmp = DllStructCreate("byte [" & DllStructGetSize($a) & "]", DllStructGetPtr($a))
    Return DllStructGetData($tmp, 1)
EndFunc   ;==>GetStructAsByte

Func ConcatStruct(ByRef $a, ByRef $b)
    $tmp = DllStructCreate("byte a[" & DllStructGetSize($a) & "]; byte b[" & DllStructGetSize($b) & "]")

    DllStructSetData($tmp, 1, GetStructAsByte($a))
    DllStructSetData($tmp, 2, GetStructAsByte($b))
    NonFreeStruct($tmp)
    Return $tmp
EndFunc   ;==>ConcatStruct

Func GetFreezeStructPtr($a)
    NonFreeStruct($a)
    Return DllStructGetPtr($a)
EndFunc

Func MakeStringBuffer($msg)
    $tmp = DllStructCreate("char[" & StringLen($msg) + 1 & "]")
    DllStructSetData($tmp, 1, $msg)
    NonFreeStruct($tmp)
    Return DllStructGetPtr($tmp)
EndFunc   ;==>MakeStringBuffer

Func MakeUnicodeBuffer($msg)
    $tmp = DllStructCreate("wchar[" & StringLen($msg) + 1 & "]")
    DllStructSetData($tmp, 1, $msg)
    NonFreeStruct($tmp)
    Return DllStructGetPtr($tmp)
EndFunc   ;==>MakeUnicodeBuffer

Func _Py_AutoitInteralError($msg, $line = $_current_line)
    print("Internal Error:" & $line & ": " & $msg)
    Exit 1
EndFunc   ;==>_Py_AutoitInteralError

Func _Py_AutoitInteralWarning($msg, $line = $_current_line)
    print("Internal Warning:" & $line & ": " & $msg)
EndFunc   ;==>_Py_AutoitInteralWarning

Func Py($funcname, $typeret, _
        $T1 = "", $P1 = "", _
        $T2 = "", $P2 = "", _
        $T3 = "", $P3 = "", _
        $T4 = "", $P4 = "", _
        $T5 = "", $P5 = "", _
        $T6 = "", $P6 = "", _
        $T7 = "", $P7 = "", _
        $T8 = "", $P8 = "", _
        $T9 = "", $P9 = "", _
        $T10 = "", $P10 = "", _
        $T11 = "", $P11 = "", _
        $T12 = "", $P12 = "", _
        $line = @ScriptLineNumber)

    Global $PyDLL
    Global $_current_line = $line

    $ERROR_POINTER_NULL = False

    If StringLen(StringStripWS($typeret, 1 + 2 + 4 + 8)) <> StringLen($typeret) Then
        _Py_AutoitInteralError("Return Type are have space")
    EndIf

    If $typeret == "ptr" Then
        $ERROR_POINTER_NULL = True
    EndIf

    $typeret &= ":cdecl"
    $funcname = "Py" & $funcname

    If @NumParams == 2 Then
        $ret = DllCall($PyDLL, $typeret, $funcname)
    ElseIf @NumParams == 4 Then
        $ret = DllCall($PyDLL, $typeret, $funcname, $T1, $P1)
    ElseIf @NumParams == 6 Then
        $ret = DllCall($PyDLL, $typeret, $funcname, $T1, $P1, $T2, $P2)
    ElseIf @NumParams == 8 Then
        $ret = DllCall($PyDLL, $typeret, $funcname, $T1, $P1, $T2, $P2, $T3, $P3)
    ElseIf @NumParams == 10 Then
        $ret = DllCall($PyDLL, $typeret, $funcname, $T1, $P1, $T2, $P2, $T3, $P3, $T4, $P4)
    ElseIf Mod(@NumParams - 3, 2) Then
        $ExecuteString = "DllCall($PyDLL, $typeret, $funcname"
        For $i = 1 To Int((@NumParams - 2) / 2)
            $ExecuteString &= ", $T" & $i & ", $P" & $i
        Next

        $ExecuteString &= ")"

        $ret = Execute($ExecuteString)
    Else
        _Py_AutoitInteralError("Wrong Argment Given")
        Return
    EndIf

    $err = @error
    $ext = @extended

    If $err Then
        Local $err_table[5] = [ _
                '0 no error (unknown!)', _
                '1 unable to use the DLL file', _
                '2 unknown "return type"', _
                '3 "function" not found in the DLL file', _
                '4 bad number of parameters' _
                ]

        _Py_AutoitInteralError("Fail Call Function (" & $funcname & ", " & $typeret & ", '" & $err_table[$err] & "', " & $ext & ")")
        Return
    EndIf

    If IsArray($ret) Then
        $ret = $ret[0]
    EndIf

    If $ERROR_POINTER_NULL And Not $ret Then
        _Py_AutoitInteralError("The Pointer are Null")
        Return
    EndIf

    If $_Py_AutoitDebug Then
        print("Return " & _Iif(StringLen($ret), $ret, "None") & @TAB & "From " & $_current_line & " line")
    EndIf

    Return $ret
EndFunc   ;==>Py
#EndRegion help functions

python code

import spam
print(spam)
print(dir(spam))
print(spam.hello)
print(3, spam.hello(3, 3))
Edited by GreenBox

Share this post


Link to post
Share on other sites



just error by space char ' '...

Share this post


Link to post
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
Sign in to follow this  
Followers 0