Author Topic: Using a Masm DLL from Python  (Read 203 times)

jj2007

  • Member
  • *****
  • Posts: 7728
  • Assembler is fun ;-)
    • MasmBasic
Using a Masm DLL from Python
« on: June 25, 2017, 09:52:03 PM »
A simple Python 3 script calling a DLL which exports Instr_():
Code: [Select]
import ctypes

hAlgos = ctypes.WinDLL("StringAlgos") # load the dll
# Instring proc ; StartPos, lpSource, lpPattern, sMode # we want only this function

print('--- find a match in "This is a string": ')
hAlgos.Instring.restype = ctypes.c_wchar_p
print(hAlgos.Instring(1,"This is a string", "string", 1))
print('---')

xstr='This is a string'.encode("ascii")
xmatch='string'.encode("ascii")

print('--- find a match in "This is a string": ')
hAlgos.Instring.restype = ctypes.c_char_p
print(hAlgos.Instring(1, xstr, xmatch, 1))
print('---')

The DLL returns a pointer to the match and provides some diagnostic feedback:
Code: [Select]
Instring proc StartPos, lpSource, lpPattern, sMode ; $export
  mov ecx, lpSource
  .if byte ptr [ecx+1] ; check if Unicode was passed
PrintLine "Source, Ascii:  ", Tb$, "[", ecx, "]"
PrintLine "Pattern, Ascii:  ", Tb$, "[", lpPattern, "]"
void Instr_(StartPos, lpSource, lpPattern, sMode)
  .else
wPrintLine "Source, Unicode:", Tb$, "[", ecx, "]"
wPrintLine "Pattern, Unicode:", wTb$, "[", lpPattern, "]"
void wInstr(StartPos, lpSource, lpPattern, sMode)
  .endif
  ret
Instring endp

Output when launched from the IDE:
Code: [Select]
Source, Unicode: [This is a string]
Pattern, Unicode: [string]
Source, Ascii:  [This is a string]
Pattern, Ascii:  [string]
--- find a match in "This is a string":
None
---
--- find a match in "This is a string":
b'string'
---

As you can see, Python does not print in the correct order. But when launched from the IDE, you can indeed instruct Python to pass ASCII or Unicode strings. Incredibly clumsy but it works.

Output when running *.py from the console:
Code: [Select]
--- find a match in "This is a string":
Source, Ascii:          [This is a string]
Pattern, Ascii:         [string]
Traceback (most recent call last):
  File "J:\Python34\tmp\Temp.py", line 8, in <module>
    print(hAlgos.Instring(1,"This is a string", "string", 1))
LookupError: unknown encoding: cp65001

Same with a different codepage:
Code: [Select]
J:\Python34>tmp\temp.py
--- find a match in "This is a string":
Source, Ascii:          [This is a string]
Pattern, Ascii:         [string]
Traceback (most recent call last):
  File "C:\Python34\tmp\Temp.py", line 8, in <module>
    print(hAlgos.Instring(1,"This is a string", "string", 1))
  File "C:\Python27\lib\encodings\cp1252.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_table)
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-2: character maps to <undefined>

So Python 3.4 uses a Python 2.7 encoding to check what it should print, and fails miserably to use the standard Windows codepage. Besides, when launched from the console it passes different args, as compared to the WinExec-type launch from the IDE.

All that is weird and messy - and some people believe that Python is the new BASIC ::)