I need to pass two Python strings, representing an input file and an output file, to a C function named decrypt_file.
If I hardcode the string (for example, 'Test.OUT'), then it works. I don't know how to use a variable string. The C function returns a string with wrong characters.
int decrypt_file(char *inputfile, char *outputfile);
try:
file_name = bytes("example.txt", encoding='utf8')
p_file_name = ctypes.create_string_buffer(file_name, len(file_name))
so = "/home/hello/lib.so"
sodium = ctypes.CDLL(so)
sodium.strfry(p_file_name)
sodium.decrypt_file.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
sodium.decrypt_file(p_file_name, ctypes.c_char_p(b"Test.OUT"))
except Exception as e:
print(e)
return -> input file: mlxta.txeep
I use Linux and Pycharm terminal. Thanks for any tips.
ctypes was wrong. I don't know if this is the right way but it works.
filename = b"helloworld.txt"
so = "/home/lib.so"
sodium = ctypes.CDLL(so)
sodium.decrypt_file.argtypes = [ctypes.POINTER(ctypes.c_char), ctypes.c_char_p]
sodium.decrypt_file(filename, ctypes.c_char_p(b"Test.OUT"))
Related
I'm trying to add my program to registry and this is my code...
def regc():
reg = windll.kernel32
print(reg)
hkey = 'HKEY_CURRENT_USER'
lsubkey = 'Software\Microsoft\Windows\CurrentVersion\Run'
reserved = 0
flag = 'REG_OPTION_BACKUP_RESTORE'
samdesired = 'KEY_ALL_ACCESS'
ipsec = None
handle = reg.RegCreateKeyExA(hkey, lsubkey, reserved, flag, samdesired, ipsec, None)
Its not giving me any errors but it still isn't creating a new key in registry. What am I doing wrong?
To use ctypes correctly, define .argtypes and .restype to do error checking of your parameters. Many of the types used are wrong. hkey, flag, and samdesired are not strings, for example. The return value is not a handle, but a status. The return value is an output parameter (pkhResult in the docs). You must read the documentation and examine the header files of all the variable definitions carefully.
Also, in Python 3 strings are Unicode, so use the W form of Windows APIs to accept Unicode strings. Use raw strings (r'...') for the subkey since it contains backslashes that could be interpreted as escape codes.
Here's a working example:
from ctypes import *
from ctypes import wintypes as w
# Values found from reading RegCreateKeyExW documentation,
# using Go To Definition on the types in Visual Studio,
# and printing constants in a C program, e.g. printf("%lx\n",KEY_ALL_ACCESS);
HKEY = c_void_p
PHKEY = POINTER(HKEY)
REGSAM = w.DWORD
LPSECURITY_ATTRIBUTES = c_void_p
LSTATUS = w.LONG
# Disposition values
REG_CREATED_NEW_KEY = 0x00000001
REG_OPENED_EXISTING_KEY = 0x00000002
ERROR_SUCCESS = 0
HKEY_CURRENT_USER = c_void_p(0x80000001)
REG_OPTION_NON_VOLATILE = 0
KEY_ALL_ACCESS = 0x000F003F
dll = WinDLL('kernel32')
dll.RegCreateKeyExW.argtypes = HKEY,w.LPCWSTR,w.DWORD,w.LPWSTR,w.DWORD,REGSAM,LPSECURITY_ATTRIBUTES,PHKEY,w.LPDWORD
dll.RegCreateKeyExW.restype = LSTATUS
hkey = HKEY_CURRENT_USER
lsubkey = r'Software\Microsoft\Windows\CurrentVersion\Run'
options = REG_OPTION_NON_VOLATILE
samdesired = KEY_ALL_ACCESS
# Storage for output parameters...pass by reference.
handle = HKEY()
disp = w.DWORD()
status = dll.RegCreateKeyExW(HKEY_CURRENT_USER, lsubkey, 0, None, options, samdesired, None, byref(handle), byref(disp))
if status == ERROR_SUCCESS:
print(f'{disp=} {handle=}')
Output:
disp=c_ulong(2) handle=c_void_p(3460)
The disposition value of 2 indicates the key already exists (REG_OPENED_EXISTING_KEY).
You could also install pywin32 and use win32api.RegCreateKey or win32api.RegCreateKeyEx where all the work is already done for you.
I have a DLL with a function
EXPORT long Util_funct( char *intext, char *outtext, int *outlen )
Looks like it expects char *intext, char *outtext, int *outlen.
I wass trying to define differnt data types in python so i can pass an argument, but no success so far.
from ctypes import *
string1 = "testrr"
#b_string1 = string1.encode('utf-8')
dll = WinDLL('util.dll')
funct = dll.Util_funct
funct.argtypes = [c_wchar_p,c_char_p, POINTER(c_int)]
funct.restype = c_char_p
p = c_int()
buf = create_string_buffer(1024)
retval = funct(string1, buf, byref(p))
print(retval)
The output is None, but I see some changes in p.
Could you please help me to define proper data types for the function.
This should work:
from ctypes import *
string1 = b'testrr' # byte string for char*
dll = CDLL('util.dll') # CDLL unless function declared __stdcall
funct = dll.Util_funct
funct.argtypes = c_char_p,c_char_p,POINTER(c_int) # c_char_p for char*
funct.restype = c_long # return value is long
p = c_int()
buf = create_string_buffer(1024) # assume this is big enough???
retval = funct(string1, buf, byref(p))
print(retval)
Thanks for all your answers!
I think i figured it out. Using not the smartest way but just trying/experimenting with different data types.
As this is not a common library and i had no information for it, maybe the sulution wont be very useful for others , but anyway.
Looks like the function process only one character at a time, because if i pass a word it returns only one encoded character.
So here it is :
from ctypes import *
buf = create_unicode_buffer(1024)
string1 = "a"
c_s = c_wchar_p(string1)
dll = CDLL('util.dll')
enc = dll.Util_funct
enc.argtypes = c_wchar_p, c_wchar_p, POINTER(c_int)
enc.restype = c_long # i don't think this type matters at all
p = c_int()
enc(c_s, buf, byref(p))
print(p.value)
print(buf.value)
the output is 1 and the simbol ^
Thanks again
I am new to Python, and I want your advice on something.
I have a script that runs one input value at a time, and I want it to be able to run a whole list of such values without me typing the values one at a time. I have a hunch that a "for loop" is needed for the main method listed below. The value is "gene_name", so effectively, i want to feed in a list of "gene_names" that the script can run through nicely.
Hope I phrased the question correctly, thanks! The chunk in question seems to be
def get_probes_from_genes(gene_names)
import json
import urllib2
import os
import pandas as pd
api_url = "http://api.brain-map.org/api/v2/data/query.json"
def get_probes_from_genes(gene_names):
if not isinstance(gene_names,list):
gene_names = [gene_names]
#in case there are white spaces in gene names
gene_names = ["'%s'"%gene_name for gene_name in gene_names]**
api_query = "?criteria=model::Probe"
api_query= ",rma::criteria,[probe_type$eq'DNA']"
api_query= ",products[abbreviation$eq'HumanMA']"
api_query= ",gene[acronym$eq%s]"%(','.join(gene_names))
api_query= ",rma::options[only$eq'probes.id','name']"
data = json.load(urllib2.urlopen(api_url api_query))
d = {probe['id']: probe['name'] for probe in data['msg']}
if not d:
raise Exception("Could not find any probes for %s gene. Check " \
"http://help.brain- map.org/download/attachments/2818165/HBA_ISH_GeneList.pdf? version=1&modificationDate=1348783035873 " \
"for list of available genes."%gene_name)
return d
def get_expression_values_from_probe_ids(probe_ids):
if not isinstance(probe_ids,list):
probe_ids = [probe_ids]
#in case there are white spaces in gene names
probe_ids = ["'%s'"%probe_id for probe_id in probe_ids]
api_query = "? criteria=service::human_microarray_expression[probes$in%s]"% (','.join(probe_ids))
data = json.load(urllib2.urlopen(api_url api_query))
expression_values = [[float(expression_value) for expression_value in data["msg"]["probes"][i]["expression_level"]] for i in range(len(probe_ids))]
well_ids = [sample["sample"]["well"] for sample in data["msg"] ["samples"]]
donor_names = [sample["donor"]["name"] for sample in data["msg"] ["samples"]]
well_coordinates = [sample["sample"]["mri"] for sample in data["msg"] ["samples"]]
return expression_values, well_ids, well_coordinates, donor_names
def get_mni_coordinates_from_wells(well_ids):
package_directory = os.path.dirname(os.path.abspath(__file__))
frame = pd.read_csv(os.path.join(package_directory, "data", "corrected_mni_coordinates.csv"), header=0, index_col=0)
return list(frame.ix[well_ids].itertuples(index=False))
if __name__ == '__main__':
probes_dict = get_probes_from_genes("SLC6A2")
expression_values, well_ids, well_coordinates, donor_names = get_expression_values_from_probe_ids(probes_dict.keys())
print get_mni_coordinates_from_wells(well_ids)
whoa, first things first. Python ain't Java, so do yourself a favor and use a nice """xxx\nyyy""" string, with triple quotes to multiline.
api_query = """?criteria=model::Probe"
,rma::criteria,[probe_type$eq'DNA']
...
"""
or something like that. you will get white spaces as typed, so you may need to adjust.
If, like suggested, you opt to loop on the call to your function through a file, you will need to either try/except your data-not-found exception or you will need to handle missing data without throwing an exception. I would opt for returning an empty result myself and letting the caller worry about what to do with it.
If you do opt for raise-ing an Exception, create your own, rather than using a generic exception. That way your code can catch your expected Exception first.
class MyNoDataFoundException(Exception):
pass
#replace your current raise code with...
if not d:
raise MyNoDataFoundException(your message here)
clarification about catching exceptions, using the accepted answer as a starting point:
if __name__ == '__main__':
with open(r"/tmp/genes.txt","r") as f:
for line in f.readlines():
#keep track of your input data
search_data = line.strip()
try:
probes_dict = get_probes_from_genes(search_data)
except MyNoDataFoundException, e:
#and do whatever you feel you need to do here...
print "bummer about search_data:%s:\nexception:%s" % (search_data, e)
expression_values, well_ids, well_coordinates, donor_names = get_expression_values_from_probe_ids(probes_dict.keys())
print get_mni_coordinates_from_wells(well_ids)
You may want to create a file with Gene names, then read content of the file and call your function in the loop. Here is an example below
if __name__ == '__main__':
with open(r"/tmp/genes.txt","r") as f:
for line in f.readlines():
probes_dict = get_probes_from_genes(line.strip())
expression_values, well_ids, well_coordinates, donor_names = get_expression_values_from_probe_ids(probes_dict.keys())
print get_mni_coordinates_from_wells(well_ids)
I am not sure what I am doing wrong here but I am trying to open a file, trace1.flow, read the header information then throw the source IP and destination IP into dictionaries. This is done in Python running on a Fedora VM. I am getting the following error:
(secs, nsecs, booted, exporter, mySourceIP, myDestinationIP) = struct.unpack('IIIIII',myBuf)
struct.error: unpack requires a string argument of length 24
Here is my code:
import struct
import socket
#Dictionaries
uniqSource = {}
uniqDestination = {}
def int2quad(i):
z = struct.pack('!I', i)
return socket.inet_ntoa(z)
myFile = open('trace1.flow')
myBuf = myFile.read(8)
(magic, endian, version, headerLen) = struct.unpack('HBBI', myBuf)
print "Magic: ", hex(magic), "Endian: ", endian, "Version: ", version, "Header Length: ", headerLen
myFile.read(headerLen - 8)
try:
while(True):
myBuf = myFile.read(24)
(secs, nsecs, booted, exporter, mySourceIP, myDestinationIP) = struct.unpack('IIIIII',myBuf)
mySourceIP = int2quad(mySourceIP)
myDestinationIP = int2quad(myDestinationIP)
if mySourceIP not in uniqSource:
uniqSource[mySourceIP] = 1
else:
uniqSource[mySourceIP] += 1
if myDestinationIP not in uniqDestination:
uniqDestination[myDestinationIP] = 1
else:
uniqDestination[myDestinationIP] += 1
myFile.read(40)
except EOFError:
print "END OF FILE"
You seem to assume that file.read will raise EOFError on end of file, but this error is only raised by input() and raw_input(). file.read will simply return a string that's shorter than requested (possibly empty).
So you need to check the length after reading:
myBuf = myFile.read(24)
if len(myBuf) < 24:
break
Perhaps your have reached end-of-file. Check the length of myBuf:
len(myBuf)
It's probably less than 24 chars long. Also you don't need those extra parenthesis, and try to specify duplicated types using 'nI' like this:
secs, nsecs, booted, exporter, mySourceIP, myDestinationIP = struct.unpack('6I',myBuf)
hi I get user argv from command line as follows: '0x000aff00'
and I want python to treat it as hex directly...
str = sys.argv[1]
how is it possible? thanks!
Try: i = int(sys.argv[1], 16)
try:
i = int(sys.argv[1], 16)
except Exception,e:
print e
else:
# carry on