Using ctypes to write binary date to clipboard, VERY bizarre bug

Not really a cry for help here, as I’ve figured out how to get this to work. This is more asking why this is behaving the way it is that has me scratching my head.

I’ve written some scripts for Blender that uses the clipboard to move data between Blender and the Natural Selection 2 map editor. It works perfectly, but only if there’s some useless code inserted in between a few key lines.

Here’s the function in question:


from ctypes import *
from binascii import hexlify
from . import SparkClasses

def SetClipboardFromString(data):
    kernel32 = windll.kernel32
    user32 = windll.user32
    memcpy = cdll.msvcrt.memcpy
    
    user32.OpenClipboard(None)
    user32.EmptyClipboard()
    
    CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")
    GPTR = 0x0040 #Flags to use when allocating global memory.
    
    hexlify(b'helloworld!') #ESSENTIAL CODE, DON'T KNOW WHY!!!  (Seriously...)
    length = len(data)
    memory_handle = kernel32.GlobalAlloc(GPTR, length)
    
    hexlify(b'helloworld!') #ESSENTIAL CODE, DON'T KNOW WHY!!!  (Seriously...)
    data_point = kernel32.GlobalLock(memory_handle)
    
    hexlify(b'helloworld!') #ESSENTIAL CODE, DON'T KNOW WHY!!!  (Seriously...)
    for i in range(0,length):
        value = int.from_bytes((data[i:i+1]), byteorder='little')
        memset(data_point+i,value,1)
        
    kernel32.GlobalUnlock(memory_handle)
    hexlify(b'helloworld!') #ESSENTIAL CODE, DON'T KNOW WHY!!!  (Seriously...)
    user32.SetClipboardData(CF_SPARK, memory_handle)
    hexlify(b'helloworld!') #ESSENTIAL CODE, DON'T KNOW WHY!!!  (Seriously...)
    user32.CloseClipboard()
    return True

Take a look at the lines that start with “hexlify”. They don’t appear to do anything. Their result isn’t being assigned to a variable, nor are they modifying any variable given to them; they’re given a byte-string literal.
Despite this, if I comment out even ONE of these “hexlify” lines, the program stops working. This code works fine in regular python, or in IDLE, but running it in Blender causes problems UNLESS I have these useless lines included.

I’ve lived with this “problem” quite happily for a while now, but now my curiosity has gotten the best of me. Can anybody think of why this is happening?

It may have something to do with Garbage collection. Have you tried to turn of the gc during your function? Other causes may be that there is some time sensitive issue, and your code “needs to wait” a really short time to make proper use of the memory? I’m neither a C guy nor a Windows guy, so I don’t know.

what if you do time.sleep(0.1) in between?

If you try to unpack the C structs yourself will it work?
http://docs.scipy.org/doc/numpy/user/basics.byteswapping.html
http://bioportal.weizmann.ac.il/course/python/PyMOTW/PyMOTW/docs/struct/index.html

This hexlify hack looks like it aligns the memory bytes but every time you call a ctype function the memory gets dis-aligned.

I remember a while ago when I first discovered this, I tried adding a pause or a delay, and it didn’t make any difference. Though I don’t remember specifically how I did this…

My memory is a little fuzzy, but the problem when I didn’t have those hexlify lines was that the memory address it was given with the GlobalLock was something invalid like 0x00000000.

When I get some free time I’m going to try to debug this a little bit more. Having it “work” because of something so strange like this just doesn’t sit right with me.