Just for fun
include \masm32\MasmBasic\MasmBasic.inc
include SetDllFolder.mac ; will be included in the next edition of MasmBasic (http://masm32.com/board/index.php?topic=94.0)
Init
SetDllFolder "\Python" ; adjust to your setup; downloaded from here (https://www.python.org/ftp/python/3.8.9/python-3.8.9-embed-win32.zip) (direct link)
Dll "python3.dll" ; python38.dll has >1600 functions; use Windows embeddable package (32-bit) here (https://www.python.org/downloads/release/python-389/)
Declare PyList_New, C:1
Declare void Py_Initialize
Declare void Py_FatalError, C:1
Declare void PySys_WriteStdout, C:? ; ?=vararg
Declare PyList_New, C:1
Declare PyList_Size, C:1 ; PyList_Size (https://docs.python.org/3/c-api/list.html?highlight=pylist_size#c.PyList_Size)(PyObject *list)
Declare PyList_SetItem, C:3 ; PyList_SetItem (https://docs.python.org/3/c-api/list.html?highlight=pylist_setitem#c.PyList_SetItem)(PyObject *list, Py_ssize_t index, PyObject *item)
Declare PyList_GetItem, C:2 ; PyList_GetItem (https://docs.python.org/3/c-api/list.html?highlight=pylist_getitem#c.PyList_GetItem)(PyObject *list, Py_ssize_t index)
Declare PyList_Sort, C:1 ; PyList_Sort (https://docs.python.org/3/c-api/list.html?highlight=pylist_sort#c.PyList_Sort)(PyObject *list); reverse flag (https://discuss.python.org/t/a-more-controllable-version-of-pylist-sort/17815)
Declare PyList_Reverse, C:1 ; PyList_SortReverse (https://docs.python.org/3/c-api/list.html?highlight=pylist_sort#c.PyList_Sort)(PyObject *list)
SetDllFolder
Py_Initialize()
Recall "\Masm32\include\Windows.inc", L$() ; load a string array (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1172)
mov edi, PyList_New(eax)
For_ ct=0 To L$(?)-1
void PyList_SetItem(edi, ct, L$(ct))
Next
Print Str$("%i elements copied\n", PyList_Size(edi))
; crashes: void PyList_Sort(edi)
Print Str$("Reversing returns %i\n", PyList_Reverse(edi)) ; string array topside down
For_ ecx=PyList_Size(edi)-1 To 0 Step -1
PrintLine Str$("%__i ", ecx), PyList_GetItem(edi, ecx)
; similar: PySys_WriteStdout(cfm$("%i\t%s\n"), ecx, PyList_GetItem(edi, ecx)) ; CRT printf under the hood...
Next
MsgBox 0, "Masm uses Python", "Hi", MB_OK
EndOfCode
Output:
26902 elements copied
26901 ;;;; head
26900
26899 comment * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
26898
26897 WINDOWS.INC for 32 bit MASM (Version 1.6 RELEASE January 2012)
26896
26895 This version is compatible with ML.EXE Version 8.0 and later.
...
4 ELSE
3 echo ------------------------------------------
2 echo WARNING Duplicate include file windows.inc
1 echo ------------------------------------------
0 ENDIF
The need for SetDllFolder is discussed here (https://masm32.com/board/index.php?msg=125434). I have no idea why the sort crashes; from an assembly pov, this is lousily documented.
See Getting a return value from the Python interpreter (https://masm32.com/board/index.php?topic=11511.0) for a different way to use Python from Assembly (), using PyRun_SimpleString().
There is a third variant using PyObject_CallMethod:
mov ioMod, PyImport_ImportModule("io")
mov openedFile, PyObject_CallMethod(ioMod, "open", "ss", "foo.txt", "wb")
Py_DecRef(ioMod)
void PyObject_CallMethod(openedFile, "write", "y", "Written from Python C API!\n")
void PyObject_CallMethod(openedFile, "flush", NULL)
void PyObject_CallMethod(openedFile, "close", NULL)
Py_DecRef(openedFile)
I also sorted out the PyList_Sort() problem (it crashed). You can't assign string pointers directly via SetItem, they must first be converted to "bytes from string", whatever that means:
For_ ct=0 To L$(?)-1
void PyList_SetItem(edi, ct, PyBytes_FromString(L$(ct)))
Next
Building the source requires MasmBasic 2 December 2023.