Page 1 of 2
Embedding Python into your apps
Posted: Mon Sep 27, 2010 9:32 pm
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

. 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
Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 7:39 am
by infratec
Hi,
thank you for your code

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

[/Edit]
Best regards,
Bernd
Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 8:24 am
by epidemicz
infratec wrote:Hi,
thank you for your code

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

.
I suppose it would be useful if I prototyped out the whole dll, I'll try to do that sometime soon.
Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 8:41 am
by Kiffi
@epidemicz: Nice! Thanks for sharing
Greetings ... Kiffi
Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 11:45 am
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
http://www.portablepython.com/wiki/Port ... 1.1Py3.0.1
Very very good idea ..thanks for sharing

Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 4:03 pm
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
Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 4:07 pm
by flaith
Purebasic with Python, cool, thanks epidemicz

Re: Embedding Python into your apps
Posted: Tue Sep 28, 2010 9:57 pm
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.
Best regards,
Bernd
Re: Embedding Python into your apps
Posted: Wed Sep 29, 2010 7:27 am
by infratec
But...
what you can do in python, what is not possible in PureBASIC
Bernd
Re: Embedding Python into your apps
Posted: Wed Sep 29, 2010 8:26 am
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.
Re: Embedding Python into your apps
Posted: Wed Sep 29, 2010 1:48 pm
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
Re: Embedding Python into your apps
Posted: Thu Jan 28, 2016 11:37 am
by Kwai chang caine
I try to use this code but unfortunately without success

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
Re: Embedding Python into your apps
Posted: Thu Jan 28, 2016 2:24 pm
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
Re: Embedding Python into your apps
Posted: Fri Jan 29, 2016 12:23 pm
by Kwai chang caine
Thanks a lot my friend, i do that
Have a good day

Re: Embedding Python into your apps
Posted: Fri Jan 29, 2016 12:29 pm
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?
