Embedding Python into your apps

Share your advanced PureBasic knowledge/code with the community.
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Embedding Python into your apps

Post by epidemicz »

There's a few things I have been wanting to work on lately and it seems like the easiest way to do them is to use python. But, I'm not satisfied with just using python, I wanna use PB too :D. I haven't seen much talk here about embedding python into a PB app, so I thought I'd give it a shot. I spent a little time researching and here's a quick example that I came up with.

**edit - I'm reposting to use infratec's example from below because mine was awful, awful and he was kind enough to correct me **

*Requires Python 3.1 (Change library name for other versions) - Get it here: http://python.org/download/ *

Code: Select all

Prototype Py_Initialize()
Prototype.s PyRun_SimpleString(String.s)
Prototype Py_Finalize()

If OpenConsole()

  If OpenLibrary(0, "python31.dll")
    PythonInitialize.Py_Initialize = GetFunction(0, "Py_Initialize")
    PythonRunSimpleString.PyRun_SimpleString = GetFunction(0, "PyRun_SimpleString")
    PythonFinalize.Py_Finalize = GetFunction(0, "Py_Finalize")
    
    PythonInitialize()
    
    pystring$ = "from time import time, ctime" + Chr(10)
    pystring$ + "print('Hello PB World from Python!')" + Chr(10)
    pystring$ + "print('Today is', ctime(time()))"
    
    PythonRunSimpleString(pystring$)
    
    PythonFinalize()
    
    CloseLibrary(0)
    
    Delay(3000)
  EndIf
  
  CloseConsole()

EndIf

Last edited by epidemicz on Tue Sep 28, 2010 3:07 pm, edited 3 times in total.
Image
infratec
Always Here
Always Here
Posts: 7620
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Embedding Python into your apps

Post by infratec »

Hi,

thank you for your code :D
Since my daughter has to learn python in school, I also started to learn it (a bit).

But I think It is not 100% clear for you how to use the prototypes in PB.

So I modified your code for python 3.1 and changed the prototype stuff

[Edit] removed my stuff, not longer neccessary :mrgreen: [/Edit]

Best regards,

Bernd
Last edited by infratec on Tue Sep 28, 2010 1:04 pm, edited 1 time in total.
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Re: Embedding Python into your apps

Post by epidemicz »

infratec wrote:Hi,

thank you for your code :D
Since my daughter has to learn python in school, I also started to learn it (a bit).

But I think It is not 100% clear for you how to use the prototypes in PB.

So I modified your code for python 3.1 and changed the prototype stuff

Best regards,

Bernd
Wow, you caught me haha. First time using prototypes, I believe, no wonder I was complaining to myself about how strange they seemed.

Really glad you showed me that, thanks!

Going to change the original post to use your code, because wow, I really goofed up. Thanks again infratec :D.

I suppose it would be useful if I prototyped out the whole dll, I'll try to do that sometime soon.
Last edited by epidemicz on Tue Sep 28, 2010 3:07 pm, edited 2 times in total.
Image
User avatar
Kiffi
Addict
Addict
Posts: 1503
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Embedding Python into your apps

Post by Kiffi »

@epidemicz: Nice! Thanks for sharing Image

Greetings ... Kiffi
Hygge
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Embedding Python into your apps

Post by Kwai chang caine »

I have also try with the portable version
ftp://ftp.heanet.ie/pub/portablepython/ ... y3.0.1.exe

That's works too, but the PB code must be in the "App" folder 8)
http://www.portablepython.com/wiki/Port ... 1.1Py3.0.1

Very very good idea ..thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Re: Embedding Python into your apps

Post by rsts »

Looks very cool. Gonna have to give it a try. Been wanting to do some python for quite a while now but hated leaving PB. This will provide the extra incentive.

Thanks for sharing.

cheers
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: Embedding Python into your apps

Post by flaith »

Purebasic with Python, cool, thanks epidemicz :D
“Fear is a reaction. Courage is a decision.” - WC
infratec
Always Here
Always Here
Posts: 7620
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Embedding Python into your apps

Post by infratec »

Hi,

hm, it was not very usefull to show stuff on the console.
So I played a bit and found the solution

Code: Select all

Prototype Py_Initialize()
Prototype.i PyRun_SimpleString(String.s)
Prototype.l PyImport_AddModule(String.s)
Prototype.l PyModule_GetDict(*Address)
Prototype.l PyDict_GetItemString(*Address, String.s)
Prototype.l PyLong_AsLong(*Address)
Prototype Py_Finalize()


If OpenLibrary(0, "python31.dll")
  Python_Initialize.Py_Initialize = GetFunction(0, "Py_Initialize")
  PythonRun_SimpleString.PyRun_SimpleString = GetFunction(0, "PyRun_SimpleString")
  
  PythonImport_AddModule.PyImport_AddModule = GetFunction(0, "PyImport_AddModule")
  PythonModule_GetDict.PyModule_GetDict = GetFunction(0, "PyModule_GetDict")
  PythonLong_AsLong.PyLong_AsLong = GetFunction(0, "PyLong_AsLong")
  PythonDict_GetItemString.PyDict_GetItemString = GetFunction(0, "PyDict_GetItemString")
  
  Python_Finalize.Py_Finalize = GetFunction(0, "Py_Finalize")
  
  Python_Initialize()
    
  PythonRun_SimpleString("result = 5 ** 2")
  *module = PythonImport_AddModule("__main__")
  *dictionary = PythonModule_GetDict(*module)
  *result = PythonDict_GetItemString(*dictionary, "result")
  Result.l = PythonLong_AsLong(*result)
  Debug Result
    
  Python_Finalize()
    
  CloseLibrary(0)
EndIf
So you can get results also without a console. :mrgreen:

Best regards,

Bernd
infratec
Always Here
Always Here
Posts: 7620
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Embedding Python into your apps

Post by infratec »

But...

what you can do in python, what is not possible in PureBASIC :?:

Bernd
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Re: Embedding Python into your apps

Post by epidemicz »

infratec wrote:But...

what you can do in python, what is not possible in PureBASIC :?:

Bernd
I think the question should be more so, how can python improve your applications.

-Quicker development time
-Easy syntax
-Cross platform
-Flexibility, it opens your app up to many more code options, libraries, etc.

Personally, my interest started when I looked into the Google Talk API. Google has released a java and python library to handle XMPP communications. So, by embedding python into my app, I can control the most minute detail of it with PB and with python I can get up and going very quickly.

I mean, its not without its downside. I'm always hesitant to bring in dependencies, but for me it's well worth it.
Image
infratec
Always Here
Always Here
Posts: 7620
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Embedding Python into your apps

Post by infratec »

Ok,

so here it is a bit more:
Save this file as Python31.pbi

Code: Select all

;
; Python 3.1 for PureBASIC
; 


PrototypeC Py_Initialize()
PrototypeC Py_Finalize()

PrototypeC Py_IncRef(*PyObject)
PrototypeC Py_DecRef(*PyObject)


PrototypeC.i PyCallable_Check(*PyObject)

PrototypeC.l PyDict_GetItemString(*PyObject, String.s)

PrototypeC PyErr_Print()
PrototypeC.l PyErr_Occurred()
PrototypeC PyErr_Clear()

PrototypeC.l PyImport_AddModule(String.s)
PrototypeC.l PyImport_Import(*PyObject)

PrototypeC.l PyLong_AsLong(*PyObject)
PrototypeC.l PyLong_FromLong(Value.l)

PrototypeC.l PyModule_GetDict(*PyObject)

PrototypeC.l PyObject_GetAttrString(*PyObject, String.s)
PrototypeC.l PyObject_CallObject(*PyObject1, *pyObject2)

PrototypeC.i PyRun_SimpleString(String.s)

PrototypeC.l PyTuple_New(Len.l)
PrototypeC.i PyTuple_SetItem(*PyObject1, Size.l, *PyObject2)

PrototypeC.l PyUnicode_FromString(String.s)




Global PythonLib.l


Structure _typeobject
    *ob_base
    *tp_name.s          ; For printing, in format "<module>.<name>"
    tp_basicsize.i
    tp_itemsize.i       ; For allocation

    ; Methods To implement standard operations

    *tp_dealloc
    *tp_print
    *tp_getattr
    *tp_setattr
    *tp_reserved     ; formerly known as tp_compare
    *tp_repr

    ; Method suites For standard classes

    *tp_as_number
    *tp_as_sequence
    *tp_as_mapping

    ; More standard operations (here For binary compatibility)

    *tp_hash
    *tp_call
    *tp_str
    *tp_getattro
    *tp_setattro

    ; Functions To access object As input/output buffer
    *tp_as_buffer

    ; Flags To Define presence of optional/expanded features
    tp_flags.l;

    *tp_doc      ; Documentation string

    ; Assigned meaning in release 2.0
    ; call function For all accessible objects
    *tp_traverse

    ; delete references To contained objects
    *tp_clear;

    ; Assigned meaning in release 2.1
    ; rich comparisons
    *tp_richcompare

    ; weak reference enabler
    tp_weaklistoffset.i

    ; Iterators
    *tp_iter
    *tp_iternext

    ; Attribute descriptor And subclassing stuff
    *tp_methods
    *tp_members
    *tp_getset
    *tp_base
    *tp_dict
    *tp_descr_get
    *tp_descr_set
    *tp_dictoffset
    *tp_init
    *tp_alloc
    *tp_new
    *tp_free      ; Low-level free-memory routine
    *tp_is_gc      ; For PyObject_IS_GC
    *tp_bases
    *tp_mro      ; method resolution order
    *tp_cache
    *tp_subclasses
    *tp_weaklist
    *tp_del

    ; Type attribute cache version tag. Added in version 2.6
    tp_version_tag.u

CompilerIf 1 = 0  ;COUNT_ALLOCS
    ; these must be last And never explicitly initialized
    tp_allocs.i
    tp_frees.i
    tp_maxalloc.i
    *tp_prev
    *tp_next
CompilerEndIf
EndStructure








Structure PythonObject
  *_ob_next
  *_ob_prev
  ob_refcnt.i
  *ob_type._typeobject
EndStructure


Macro Python_INCREF(op)
  op\ob_refcnt + 1
EndMacro

Macro Python_XINCREF(op)
  If op : Python_INCREF(op) : EndIf
EndMacro

Macro Python_DECREF(op)
  op\ob_refcnt - 1
  If op\ob_refcnt <> 0
    ; Don't know how to do it
  Else
    ; Don't know how to do it
  EndIf
EndMacro

Macro Python_XDECREF(op)
  If op : Python_DECREF(op) : EndIf
EndMacro

Macro Python_CLEAR()
  If op
    *_py_tmp = op
    op = #Null
    Py_DECREF(*_py_tmp)
  EndIf
EndMacro



Procedure.i PythonInit()
  
  PythonLib = OpenLibrary(#PB_Any, "python31.dll")
  If PythonLib
    Global Python_Initialize.Py_Initialize = GetFunction(PythonLib, "Py_Initialize")
    Global Python_Finalize.Py_Finalize = GetFunction(PythonLib, "Py_Finalize")
    
    Global Python_IncRef.Py_IncRef = GetFunction(PythonLib, "Py_IncRef")
    Global Python_DecRef.Py_DecRef = GetFunction(PythonLib, "Py_DecRef")
    
    Global PythonCallable_Check.PyCallable_Check = GetFunction(PythonLib, "PyCallable_Check")
    
    Global PythonDict_GetItemString.PyDict_GetItemString = GetFunction(PythonLib, "PyDict_GetItemString")
    
    Global PythonErr_Print.PyErr_Print = GetFunction(PythonLib, "PyErr_Print")
    Global PythonErr_Occurred.PyErr_Occurred = GetFunction(PythonLib, "PyErr_Occurred")
    Global PythonErr_Clear.PyErr_Clear = GetFunction(PythonLib, "PyErr_Clear")
    
    Global PythonImport_AddModule.PyImport_AddModule = GetFunction(PythonLib, "PyImport_AddModule")
    Global PythonImport_Import.PyImport_Import = GetFunction(PythonLib, "PyImport_Import")
    
    Global PythonLong_AsLong.PyLong_AsLong = GetFunction(PythonLib, "PyLong_AsLong")
    Global PythonLong_FromLong.PyLong_FromLong = GetFunction(PythonLib, "PyLong_FromLong")
    
    Global PythonModule_GetDict.PyModule_GetDict = GetFunction(PythonLib, "PyModule_GetDict")
    
    Global PythonObject_GetAttrString.PyObject_GetAttrString = GetFunction(PythonLib, "PyObject_GetAttrString")
    Global PythonObject_CallObject.PyObject_CallObject = GetFunction(PythonLib, "PyObject_CallObject")
    
    Global PythonRun_SimpleString.PyRun_SimpleString = GetFunction(PythonLib, "PyRun_SimpleString")
    
    Global PythonTuple_New.PyTuple_New = GetFunction(PythonLib, "PyTuple_New")
    Global PythonTuple_SetItem.PyTuple_SetItem = GetFunction(PythonLib, "PyTuple_SetItem")
    
    Global PythonUnicode_FromString.PyUnicode_FromString = GetFunction(PythonLib, "PyUnicode_InternFromString")
  EndIf
  
  ProcedureReturn PythonLib
  
EndProcedure


Procedure PythonClose()
  
  If PythonLib
    CloseLibrary(PythonLib)
  EndIf
  
EndProcedure
Save this file as callpy.pb

Code: Select all

IncludeFile "Python31.pbi"




If OpenConsole()

  If CountProgramParameters() < 2
    PrintN("Usage: call pythonfile funcname [args]")    
    End 1
  EndIf
  
  If PythonInit()
    Python_Initialize()
    
    Debug ProgramParameter(0)
    
    *pName.PythonObject = PythonUnicode_FromString(ProgramParameter(0))
    ; Error checking of pName left out

    *pModule.PythonObject = PythonImport_Import(*pName)
    Python_DECREF(*pName)
    
    Debug ProgramParameter(1)
    
    If *pModule
      *pFunc.PythonObject = PythonObject_GetAttrString(*pModule, ProgramParameter(1))
      ; pFunc is a new reference
      If *pFunc And PythonCallable_Check(*pFunc)
        *pArgs.PythonObject = PythonTuple_New(CountProgramParameters() - 2)
        
        For i = 0 To CountProgramParameters() - 3
          *pValue.PythonObject = PythonLong_FromLong(Val(ProgramParameter(i + 2)))
          If Not *pValue
            Python_DECREF(*pArgs)
            Python_DECREF(*pModule);
            PrintN("Cannot convert argument")
            End 1
          EndIf
          ; pValue reference stolen here:
          PythonTuple_SetItem(*pArgs, i, *pValue)
        Next i
        
        *pValue.PythonObject = PythonObject_CallObject(*pFunc, *pArgs)
        Python_DECREF(*pArgs)
        If *pValue <> #Null
          PrintN("Result of call: " +  Str(PythonLong_AsLong(*pValue)))
          Python_DECREF(*pValue)
        Else
          Python_DECREF(*pFunc)
          Python_DECREF(*pModule)
          PythonErr_Print()
          PrintN("Call failed")
          End 1
        EndIf
        
      Else
        If PythonErr_Occurred()
          PythonErr_Print()
          PrintN("Cannot find function " + ProgramParameter(1))
        EndIf
      EndIf
      
    Else
      PythonErr_Print()
      PrintN("Failed to load " + ProgramParameter(0))
      End 1
    EndIf
       
    Python_Finalize()
  EndIf
  
  CloseConsole()
EndIf
And this as first.py

Code: Select all

def multiply(a,b):
    print("Will compute", a, "times", b)
    c = 0
    for i in range(0, a):
        c = c + b
    return c

#print(multiply1(4,2))
Than you should be able to do
callpy first multiply 2 3
at the console.

This is the example from the python tutorial converted to PureBASIC.

But unfortunately I miss something in the pbi file.
If someone has a solution, tell it.
(Look at the macro Python_DECREF)

Bernd
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Embedding Python into your apps

Post by Kwai chang caine »

I try to use this code but unfortunately without success :cry:
The worst it's before i try it, but now i not find the "python31.dll" and with the "python30.dll" i have an error at the line "Python_Initialize()" in the "Microsoft Visual C++ Runtime Library" with this text "This application has requested the Runtime to terminate it in an unusual way.Please contact the application's support team for more information."
I have try with pb v4.30, v4.51, 5.23 and nothing better :|
I use now W7, it's perhaps this the problem :?:

Someone have the correct PYTHON for use this code, or better the code for use one of the last PYTHON, for exampler 3.4 because i have the DLL
ImageThe happiness is a road...
Not a destination
infratec
Always Here
Always Here
Posts: 7620
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Embedding Python into your apps

Post by infratec »

Hi KCC,

less time, so ...

You can download Python 3.1.4
https://www.python.org/ftp/python/3.1.4 ... -3.1.4.msi
https://www.python.org/ftp/python/3.1.4 ... .amd64.msi

Install it,
copy the python31.dll from \windows\system32\ to a save place,
uninstall it

With this dll the example works. (just tested) Win7 x64 PB 5.41 x86 and python 3.1.4 x86

Bernd
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Embedding Python into your apps

Post by Kwai chang caine »

Thanks a lot my friend, i do that
Have a good day 8)
ImageThe happiness is a road...
Not a destination
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Embedding Python into your apps

Post by Dude »

infratec wrote:what you can do in python, what is not possible in PureBASIC :?:
It constantly amazes me that people buy PureBasic but then still want to mix Python, machine code, OOP, and all other non-Basic stuff to it. Doesn't anyone buy it just for Basic anymore? :lol:
Post Reply