thank you for your time reading this, this bugs me long time.I'm using Python3.8 and using ctypes to call a DLL. In most of cases ,ctypes works like charm.
One function from C DLL will output a list of names i.e
int get_date(char* names[]) // each name has length 10, with size of 5
in Python I'm successfully call it like
string_buffers = [ctypes.create_string_buffer(10) for i in range(5)]
char_array = (ctypes.c_char_p*5)(*map(ctypes.addressof, string_buffers))
handler.get_date(char_array)
But I am try to factor out a function to create such case :
def create_char_p_array(length:int, size:int):
string_buffers = [create_string_buffer(length) for i in range(size)]
ia = (c_char_p*size)(*map(addressof, string_buffers))
return ia
char_array = create_char_p_array(10,5)
handler.get_date(char_array) ### failed, or ,crashed, or random value ###
So to narrow down the issue, I move out the map(addressof) out, it magically works! :
def create_char_p_array(length:int, size:int):
string_buffers = [create_string_buffer(length) for i in range(size)]
return string_buffers
sbrs = create_char_p_array(10,5)
char_array = (c_char_p*5)(*map(addressof, sbrs ))
handler.get_date(char_array) # Success !
Is it because create_string_buffer created in function scope will be wipe out once the function create_char_p_array return ?
Thank you for your time ,much appreciated.
Here's what I came up with. addressof doesn't create a reference to the object it operates on. cast will.
test.c:
#include <string.h>
__declspec(dllexport) int get_date(char* names[])
{
strcpy_s(names[0],10,"One");
strcpy_s(names[1],10,"Two");
strcpy_s(names[2],10,"Three");
strcpy_s(names[3],10,"Four");
strcpy_s(names[4],10,"Five");
return 5;
}
test.py:
from ctypes import *
dll = CDLL('./x')
dll.get_date.argtypes = POINTER(c_char_p),
dll.get_date.restype = c_int
def create_char_p_array(length:int, size:int):
return (c_char_p*size)(*[cast(create_string_buffer(length),c_char_p) for _ in range(size)])
a = create_char_p_array(10,5)
dll.get_date(a)
for s in a:
print(s)
Output:
b'One'
b'Two'
b'Three'
b'Four'
b'Five'
Related
The above script is supposed to take in user input as a string. The string will look something like this "120,50" where 120 is x coordinate and 50 is y coordinate. I wrote a function called “judge” that will take the user input, split it in two (x and y) and then check if either x or y are more than 127 or less than -127. If that is the case, it should add or subtract 127 from the x/y value. This is done to get the difference. It then adds the 127 (or subtracts) that it took originally to get the difference. After this calculation, the values are sent to an arduino where the mouse is moved accordingly.
main.py on host
import serial, serial.tools.list_ports
import win32api
from time import sleep
# print list of available comports
ports = list(serial.tools.list_ports.comports())
for _ in ports:
print(_)
# establish connection with given comport
comport = input("Enter comport: COM")
ser = serial.Serial(f"COM{comport}", 115200)
# send coordinates in bytes
def write_read(x):
ser.write(x.encode("utf-8"))
def judge(num, append_string_x, append_string_y):
x, y = num.split(",")
if int(x) > 127:
append_string_x = str(int(x) - 127)
# ADD 127 AFTER SENDING
write_read("127,0")
sleep(0.01) # Sleep is used to circumvent a bug I found
elif int(x) < -127:
append_string_x = str(int(x) + 127)
# SUBTRACT 127 AFTER SEND
write_read("-127,0")
sleep(0.01) # Sleep is used to circumvent a bug I found
else:
append_string_x = str(x)
if int(y) > 127:
append_string_y = str(int(y) - 127)
# ADD 127 AFTER SENDING
write_read("0,127")
sleep(0.01) # Sleep is used to circumvent a bug I found
elif int(y) < -127:
append_string_y = str(int(y) + 127)
# SUBTRACT 127 AFTER SENDING
write_read("0,-127")
sleep(0.01) # Sleep is used to circumvent a bug I found
else:
append_string_y = str(y)
x_y = f"{append_string_x},{append_string_y}"
write_read(x_y)
sleep(0.01) # Sleep is used to circumvent a bug I found
# main while loop
while True:
num = input("Enter a number: ")
judge(num, append_string_x="", append_string_y="")
main.c on arduino
#include "HID-Project.h"
void setup() {
Serial.begin(115200);
Serial.setTimeout(1); // This shit almost gave me a heart attack
Mouse.begin();
}
void loop()
{
if(Serial.available() > 0)
{
String str = Serial.readStringUntil(',');
int dx = str.toInt();
int dy = Serial.parseInt();
mouse_move(dx, dy);
}
}
void mouse_move(int dx, int dy)
{
Mouse.move(dx, dy);
}
Behavior WITHOUT the sleep(0.01) call in main.py
Why is there y-axis movement when the sleep(0.01) call isn't included in main.py?
Edit: I am using Arduino Micro atmega32u4 if that helps.
There is no "end-of-number" character between your ser.writes. This may cause numbers to arrive adjacent to each other, causing your read functions to read incorrect integers.
write_read("0,-127")
...
x_y = f"{append_string_x},{append_string_y}"
write_read(x_y)
So -127 and x will be read on the Arduino side concatenated (as one string).
You could fix this by sending additional separators ,:
write_read("0,-127,")
When I am running a pyopengl program, I get an error.
I searhed the web but all it says is that it is a pyopengl version problem, but I am using the latest update.
Traceback (most recent call last):
File "C:/Users/TheUser/Desktop/MyPytonDen/ThinMatrixOpenGl/engineTester/MainGameLoop.py", line 10, in
from ThinMatrixOpenGl.renderEngine.MasterRenderer import MasterRendererClass
File "C:\Users\TheUser\Desktop\MyPytonDen\ThinMatrixOpenGl\renderEngine\MasterRenderer.py", line 10, in
class MasterRendererClass:
File "C:\Users\TheUser\Desktop\MyPytonDen\ThinMatrixOpenGl\renderEngine\MasterRenderer.py", line 11, in MasterRendererClass
shader = StaticShaderClass()
File "C:\Users\TheUser\Desktop\MyPytonDen\ThinMatrixOpenGl\shaders\staticShader.py", line 22, in init
super().init(self.VERTEX_FILE, self.FRAGMENT_FILE)
File "C:\Users\TheUser\Desktop\MyPytonDen\ThinMatrixOpenGl\shaders\shaderProgram.py", line 13, in init
self.Vertex_Shader_Id = Load_Shader(vertex_file, GL_VERTEX_SHADER)
File "C:\Users\TheUser\Desktop\MyPytonDen\ThinMatrixOpenGl\shaders\shaderProgram.py", line 84, in Load_Shader
Shader_Id = glCreateShader(type_of_shader)
File "C:\Users\TheUser\AppData\Local\Programs\Python\Python38-32\lib\site-packages\OpenGL\platform\baseplatform.py", line 423, in call
raise error.NullFunctionError(
OpenGL.error.NullFunctionError: Attempt to call an undefined function glCreateShader, check for bool(glCreateShader) before calling
Process finished with exit code 1
I checked the OpenGL source code. Not that I meddle with it in the first place but its fine.
For some reason, StaticShader refuses to initialize now.
In my program, before doing some change, it was working just fine and it is still working in some other project.
Despite I didn't even get close to shader codes it gave me this.
What exactly is this and how can I handle it.
Btw while this poped up I was trying to update the render algorithm although it did not change much.
class StaticShaderClass(ShaderProgramClass):
VERTEX_FILE = "../shaders/vertexShader.txt"
FRAGMENT_FILE = "../shaders/fragmentShader.txt"
location_transformation_matrix: int
location_projection_matrix: int
location_view_matrix: int
location_light_position: int
location_light_color: int
location_shine_damper: int
location_reflectivity: int
def __init__(self):
super().__init__(self.VERTEX_FILE, self.FRAGMENT_FILE)
def Bind_Attributes(self):
super().Bind_Attribute(0, "position")
super().Bind_Attribute(1, "texture_coord")
super().Bind_Attribute(2, "normal")
def GetAllUniformLocation(self):
self.location_transformation_matrix = super().GetUniformLocation("transformation_matrix")
self.location_projection_matrix = super().GetUniformLocation("projection_matrix")
self.location_view_matrix = super().GetUniformLocation("view_matrix")
self.location_light_position = super().GetUniformLocation("light_position")
self.location_light_color = super().GetUniformLocation("light_color")
self.location_shine_damper = super().GetUniformLocation("shine_damper")
self.location_reflectivity = super().GetUniformLocation("reflectivity")
def Load_Shine_Variables(self, damper, reflectivity):
Load_Float(self.location_shine_damper, damper)
Load_Float(self.location_reflectivity, reflectivity)
def Load_Transformation_Matrix(self, matrix: Matrix44):
super().Load_Matrix(self.location_transformation_matrix, matrix)
def Load_Projection_Matrix(self, projection: Matrix44):
super().Load_Matrix(self.location_projection_matrix, projection)
def Load_view_Matrix(self, camera: CameraClass):
view_matrix = Maths.Create_view_Matrix(camera)
super().Load_Matrix(self.location_view_matrix, view_matrix)
def Load_Light(self, light: Light):
Load_Vector(self.location_light_position, light.position)
Load_Vector(self.location_light_color, light.color)
class ShaderProgramClass(ABC):
Program_Id: int
Vertex_Shader_Id: int
Fragment_Shader_Id: int
def __init__(self, vertex_file: str, fragment_file: str):
self.Vertex_Shader_Id = Load_Shader(vertex_file, GL_VERTEX_SHADER)
self.Fragment_Shader_Id = Load_Shader(fragment_file, GL_FRAGMENT_SHADER)
self.Program_Id = glCreateProgram()
glAttachShader(self.Program_Id, self.Vertex_Shader_Id)
glAttachShader(self.Program_Id, self.Fragment_Shader_Id)
self.Bind_Attributes()
glLinkProgram(self.Program_Id)
# glGetProgramInfoLog(self.Program_Id)
glValidateProgram(self.Program_Id)
self.GetAllUniformLocation()
def Start(self):
glUseProgram(self.Program_Id)
def Clean_up(self):
self.Stop()
glDetachShader(self.Program_Id, self.Vertex_Shader_Id)
glDetachShader(self.Program_Id, self.Fragment_Shader_Id)
glDeleteShader(self.Vertex_Shader_Id)
glDeleteShader(self.Fragment_Shader_Id)
glDeleteProgram(self.Program_Id)
#abstractmethod
def Bind_Attributes(self):
pass
def Bind_Attribute(self, attribute: int, variable_name: str):
glBindAttribLocation(self.Program_Id, attribute, variable_name)
#staticmethod
def Stop():
glUseProgram(0)
#abstractmethod
def GetAllUniformLocation(self):
pass
def GetUniformLocation(self, uniform_name: str):
return glGetUniformLocation(self.Program_Id, uniform_name)
#staticmethod
def Load_Matrix(location, matrix):
matrix = np.array(matrix, dtype=np.float32)
# it may require matrix s data type to change float later
glUniformMatrix4fv(location, 1, False, matrix)
def Load_Float(location: int, value: float):
glUniform1f(location, value)
def Load_Vector(location: int, vector: Vector3):
glUniform3f(location, vector.x, vector.y, vector.z)
def Load_Boolean(location: int, value: bool):
to_load = 0
if value:
to_load = 1
glUniform1f(location, to_load)
def Load_Shader(file: str, type_of_shader: int):
try:
src = ""
with open(file, "r") as f:
text = f.readlines()
for i in text:
src += str(i)
except ():
raise Exception(FileNotFoundError, "file is not exist or could not be readied for some reason")
Shader_Id = glCreateShader(type_of_shader)
print(Shader_Id)
glShaderSource(Shader_Id, src)
glCompileShader(Shader_Id)
if glGetShaderiv(Shader_Id, GL_COMPILE_STATUS) == GL_FALSE:
print(glGetShaderInfoLog(Shader_Id))
print("could not compile shader!")
return Shader_Id
#version 400 core
in vec3 position;
in vec2 texture_coord;
in vec3 normal;
out vec2 pass_texture_coord;
out vec3 surface_normal;
out vec3 to_light_vector;
out vec3 to_camera_vector;
uniform mat4 transformation_matrix;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform vec3 light_position;
void main(){
vec4 world_position = transformation_matrix * vec4(position, 1.0f);
gl_Position = projection_matrix * view_matrix * world_position;
pass_texture_coord = texture_coord;
surface_normal = (transformation_matrix * vec4(normal,0.0)).xyz;
to_light_vector = light_position - world_position.xyz;
to_camera_vector = (inverse(view_matrix) * vec4(0.0,0.0,0.0,1.0)).xyz - world_position.xyz;
}
Let me quote Python class attributes are evaluated on declaration:
In Python, class attributes are evaluated and put into memory when the class is defined (or imported).
A valid and current OpenGL context is required for each OpenGL instruction, such as for creating the shader program. Therefore, if the shader program is stored in a class attribute and the class is defined or imported before the OpenGL window and context are created, the shader program cannot be generated.
I show you below an example of code using pycuda with "kernel" code included in itself (with SourceModule)
import pycuda
import pycuda.driver as cuda
from pycuda.compiler import SourceModule
import threading
import numpy
class GPUThread(threading.Thread):
def __init__(self, number, some_array):
threading.Thread.__init__(self)
self.number = number
self.some_array = some_array
def run(self):
self.dev = cuda.Device(self.number)
self.ctx = self.dev.make_context()
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
cuda.memcpy_htod(self.array_gpu, some_array)
test_kernel(self.array_gpu)
print "successful exit from thread %d" % self.number
self.ctx.pop()
del self.array_gpu
del self.ctx
def test_kernel(input_array_gpu):
mod = SourceModule("""
__global__ void f(float * out, float * in)
{
int idx = threadIdx.x;
out[idx] = in[idx] + 6;
}
""")
func = mod.get_function("f")
output_array = numpy.zeros((1,512))
output_array_gpu = cuda.mem_alloc(output_array.nbytes)
func(output_array_gpu,
input_array_gpu,
block=(512,1,1))
cuda.memcpy_dtoh(output_array, output_array_gpu)
return output_array
cuda.init()
some_array = numpy.ones((1,512), dtype=numpy.float32)
num = cuda.Device.count()
gpu_thread_list = []
for i in range(num):
gpu_thread = GPUThread(i, some_array)
gpu_thread.start()
gpu_thread_list.append(gpu_thread)
I would like to use the same method but instead of using a "kernel code", I would like to do multiple calls of a function which is external (not a function like "kernel code"), i.e a classical function defined in my main program and which takes in argument different parameters shared by all the main program. Is it possible ?
People who have practiced Matlab may know the function arrayfun where B = arrayfun(func,A) is a vector of results given by applying function funcfor each element of vector A.
Actually, it is a version of what is commonly called the map function: I would like to do the same but with GPU/pycuda version.
Update 1
Sorry, I forgot from the beginning of my post to say what I call an extern and classical function. Here is below an example of function which is used in main section :
def integ(I1):
function_A = aux_fun_LU(way, ecs, I1[0], I1[1])
integrale_A = 0.25*delta_x*delta_y*np.sum(function_A[0:-1, 0:-1] + function_A[1:, 0:-1] + function_A[0:-1, 1:] + function_A[1:, 1:])
def g():
for j in range(6*i, 6*i+6):
for l in range(j, 6*i+6):
yield j, l
## applied integ function to g() generator.
## Here I a using simple map function (no parallelization)
if __name__ == '__main__':
map(integ, g())
Update 2
Maybe a solution would be to call the extern function from a kernel code, benefiting as well of the high GPU power of multiple calls on kernel code. But how to deal with the returned value of this extern function to get it back into main program?
Update 3
Here is below what I have tried:
# Class GPUThread
class GPUThread(threading.Thread):
def __init__(self, number, some_array):
threading.Thread.__init__(self)
self.number = number
self.some_array = some_array
def run(self):
self.dev = cuda.Device(self.number)
self.ctx = self.dev.make_context()
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
cuda.memcpy_htod(self.array_gpu, some_array)
test_kernel(self.array_gpu)
print "successful exit from thread %d" % self.number
self.ctx.pop()
del self.array_gpu
del self.ctx
def test_kernel(input_array_gpu):
mod1 = SourceModule("""
__device__ void integ1(int *I1)
{
function_A = aux_fun_LU(way, ecs, I1[0], I1[1]);
integrale_A = 0.25*delta_x*delta_y*np.sum(function_A[0:-1, 0:-1] + function_A[1:, 0:-1] + function_A[0:-1, 1:] + function_A[1:, 1:]);
}""")
func1 = mod1.get_function("integ1")
# Calling function
func1(input_array_gpu)
# Define couples (i,j) to build Fisher matrix
def g1():
for j in range(6*i, 6*i+6):
for l in range(j, 6*i+6):
yield j, l
# Cuda init
if __name__ == '__main__':
cuda.init()
# Input gTotal lists
some_array1 = np.array(list(g1()))
print 'some_array1 = ', some_array1
# Parameters for cuda
num = cuda.Device.count()
gpu_thread_list = []
for i in range(num):
gpu_thread = GPUThread(i, some_array1)
#gpu_thread = GPUThread(i, eval("some_array"+str(j)))
gpu_thread.start()
gpu_thread_list.append(gpu_thread)
I get the following error at the execution:
`Traceback (most recent call last):
File "/Users/mike/anaconda2/envs/py2cuda/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "Example_GPU.py", line 1232, in run
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
NameError: global name 'some_array' is not defined`
I can't see what's wrong with the variable 'some_array' and the line
self.array_gpu = cuda.mem_alloc(some_array.nbytes)
What can I try next?
I am looking for a way to port R code to Python. I wonder if anyone knows of some way to do a rough translation, to facilitate porting. Note that I am not interested in running R from Python, or Python from R - I want native Python from existing R code. I have written a few functions in R that translate a few language features automatically:
gsub.R.to.python <- function(x)
{
# very crude conversion of R code to python - facilitating manual port
out <- gsub.function.to.def(x)
out <- gsub(pattern = "<-","=",out)
out <- gsub.dots.to.underscore(out)
out <- gsub.python.remove.brackets(out)
out <- gsub.T.to.True(out)
out <- gsub.F.to.False(out)
cat(out)
invisible(out)
}
gsub.dots.to.underscore <- function(x)
{
# replace dots to underscores in variable names (i.e. between letters)
# gsub.dots.to.underscore(c("a.b","1.0")) --> "a_b" "1.0"
out <- gsub(pattern = "(?<=[a-zA-Z])\\.(?=[a-zA-Z])","_",x,perl = T)
return(out)
}
gsub.function.to.def <- function(x)
{
# change all function lines - use perl multiline searching
out <- gsub("(?m)^([a-zA-Z].+?) <- function\\((.+?)\\)","def \\1(\\2):",x,perl = T)
return(out)
}
gsub.python.remove.brackets<- function(x)
{
# get rid of brackets on their own lines
out <- gsub("(?m)^\\s*\\{\\s*$","",x,perl = T)
out <- gsub("(?m)^\\s*\\}\\s*$","",out,perl = T)
return(out)
}
gsub.T.to.True <- function(x) gsub("\\bT\\b|\\bTRUE\\b","True",x)
gsub.F.to.False <- function(x) gsub("\\bF\\b|\\bFALSE\\b","False",x)
Running gsub.R.to.python() on a block of R code produces a block of Python-ish gibberish that is a bit easier to translate into Python. I am looking for a better / more complete version of this idea, or some other tool to help in the porting process.
For example, running this code in R on the code itself, produces the following:
def gsub_R_to_python(x):
# very crude conversion of R code to python - facilitating manual port
out = gsub_function_to_def(x)
out = gsub(pattern = "=","=",out)
out = gsub_dots_to_underscore(out)
out = gsub_python_remove_brackets(out)
out = gsub_T_to_True(out)
out = gsub_F_to_False(out)
cat(out)
invisible(out)
def gsub_dots_to_underscore(x):
# replace dots to underscores in variable names (i_e. between letters)
# gsub_dots_to_underscore(c("a_b","1.0")) --> "a_b" "1.0"
out = gsub(pattern = "(?<=[a-zA-Z])\.(?=[a-zA-Z])","_",x,perl = True)
return(out)
def gsub_function_to_def(x):
# change all function lines - use perl multiline searching
out = gsub("(?m)^([a-zA-Z].+?) = function\((.+?)\)","def \1(\2):",x,perl = True)
return(out)
gsub_python_remove_brackets= function(x)
# get rid of brackets on their own lines
out = gsub("(?m)^\s*\{\s*$","",x,perl = True)
out = gsub("(?m)^\s*\}\s*$","",out,perl = True)
return(out)
def gsub_T_to_True(x): gsub("\bT\b|\bTRUE\b","True",x)
def gsub_F_to_False(x): gsub("\bF\b|\bFALSE\b","False",x)
I'm trying to make a python wrapper for AutoIt using ctypes.
Here is my problem:
e.g. The prototype for AU3_WinGetText is:
void AU3_WinGetTitle(LPCWSTR szTitle, LPCWSTR szText, LPWSTR szRetText, int nBufSize);
I'm using flowing code to call the function:
import ctypes
from ctypes.wintypes import *
AUTOIT = ctypes.windll.LoadLibrary("AutoItX3.dll")
def win_get_title(title, text="", buf_size=200):
AUTOIT.AU3_WinGetTitle.argtypes = (LPCWSTR, LPCWSTR, LPWSTR, INT)
AUTOIT.AU3_WinGetTitle.restypes = None
rec_text = LPWSTR()
AUTOIT.AU3_WinGetTitle(LPCWSTR(title), LPCWSTR(text),
ctypes.cast(ctypes.byref(rec_text), LPWSTR),
INT(buf_size))
res = rec_text.value
return res
print win_get_title("[CLASS:Notepad]")
I'm getting an exception after run these codes:
res = rec_text.value
ValueError: invalid string pointer 0x680765E0
szRetText is used to receive the output text buffer
import ctypes
from ctypes.wintypes import *
AUTOIT = ctypes.windll.LoadLibrary("AutoItX3.dll")
def win_get_title(title, text="", buf_size=200):
# AUTOIT.AU3_WinGetTitle.argtypes = (LPCWSTR, LPCWSTR, LPWSTR, INT)
# AUTOIT.AU3_WinGetTitle.restypes = None
rec_text = ctypes.create_unicode_buffer(buf_size)
AUTOIT.AU3_WinGetTitle(LPCWSTR(title), LPCWSTR(text),
rec_text, INT(buf_size))
res = rec_text.value.rstrip()
return res
print win_get_title("[CLASS:Notepad]")