I am calling some c-sdk from python code. This python code is running as lambda on greengrass. I am using cffi to call the function of shared so from python. My lambda (python code) is running as gcc_user but when i print the user in my C code, it prints something like: T� Pp.
Below is the C code that i am using to print the user info:
char* username[10];
getlogin_r(username, 10);
printf("current user in c program ");
for(index = 0;index<10; index++)
{
printf("%c",username[index]);
}
printf("\n");
Below is the python code that i am using call the shared lib (C code):
import cffi
import _cffi_backend
from sys import exit, platform
import boto3
from multiprocessing import Process
import sys, os
import logging
import getpass
def StartVideoStreaming(channelName):
ffi = cffi.FFI()
cdef_from_file = None
header = '/home/admin/alprwebrtcdemo/amazon-kinesis-video-streams-webrtc-sdk-c/samples/kvsWebRTCClientMasterGstreamer.h'
try:
with open(header, 'r') as libtestcffi_header:
cdef_from_file = libtestcffi_header.read()
except FileNotFoundError:
print('Unable to find "%s"' % header)
exit(2)
except IOError:
print('Unable to open "%s"' % header)
exit(3)
finally:
if cdef_from_file == '':
print('File "%s" is empty' % header)
exit(1)
ffi.cdef(cdef_from_file)
lib_extension = ''
if platform.startswith('freebsd') or platform.startswith('linux'):
lib_extension = 'so'
elif platform.startswith('win'):
lib_extension = 'dll'
CLibTC = ffi.dlopen('/home/admin/alprwebrtcdemo/amazon-kinesis-video-streams-webrtc-sdk-c/build/liblibkvsWebrtcClientMasterGstSample.' + lib_extension)
arg_0 = "arg0".encode('utf-8')
arg_1 = channelName.encode('utf-8')
argv_keepalive = [ffi.new("char[]", arg_0),
ffi.new("char[]", arg_1)]
argv = ffi.new("char *[]", argv_keepalive)
session = boto3.Session()
logging.info("user in process: {}".format(getpass.getuser()))
credentials = session.get_credentials()
accountKeyID = credentials.access_key
accountSecret = credentials.secret_key
sessionToken = credentials.token
logging.info("ID: {}, secret: {}, session: {}".format(accountKeyID, accountSecret, sessionToken))
arg1 = accountKeyID.encode('utf-8')
arg2 = accountSecret.encode('utf-8')
arg3 = sessionToken.encode('utf-8')
CLibTC.start(2,argv,arg1,arg2,arg3)
print('Everything is fine!!!')
def main():
logging.info("XDG_CACHE_HOME env variable value: {}".format(os.environ.get(HOME)))
logging.info("user in python: {}".format(getpass.getuser()))
sys.path.insert(0,'')
p1 = Process(target=StartVideoStreaming, args=('channeltest666',))
p1.start()
p1.join()
Is there a way to call c lib from python and force it to run as gcc_user? According to me it should have been running as gcc_user at first place because its just a function call from python code.
It should be char username [10], without the *. Maybe there are other problems too but try to fix that first.
Related
import os
def findFiles(root_dir="C:/Users/15025/Desktop/books/", res=None):
if not res:
res = []
for f in os.listdir(root_dir):
f_path = os.path.join(root_dir, f)
if os.path.isfile(f_path):
res.append(f_path)
elif os.path.isdir(f_path):
findFiles(f_path, res)
return res
result = findFiles()
print(result)
I find some problems here, if I have a file under "C:/Users/15025/Desktop/books/" directory, like deepLearning, and in this deepLearning file I have a document named debug.py. But when I run this program, the print(result)shows nothing, it is strange. Could someone tell me why? I think it is because the program will be called twice. But what is the reason in detail?
The figure of my directory and the running result could seen below:
WTF, I feel I always answer my own question, finally, I find that I should change findFiles(f_path, res) to res = findFiles(f_path, res), and then everything is fine.
I have some functions like the below sample. The objective is to pass the first function as an argument to the second function and use numba to speed it up. But if I turn the cache=True for the second function, there will be error message:
TypeError: can't pickle weakref objects
My numba version is 0.49.0
Is there any solution/alternative solution to this problem so that I can cache the compilation?
#njit(cache=True)
def func_test(t1, t2):
return np.corrcoef(np.argsort(np.argsort(t1)), np.argsort(np.argsort(t2)))
#njit(cache=True)
def test_func_input2(func_1):
t = list(range(500))
t2 = list(range(500))
for i in range(1000):
t.pop(0)
t2.pop(0)
t.append(i)
t2.append(i)
a = np.array(t)
b = np.array(t2)
x = func_1(a, b)
return x
if __name__ == '__main__':
import numpy as np
test_func_input2(func_test)
For a file path name such as
val path = "$HOME/projects/$P1/myFile.txt"
is there a simpler way to resolve the path and read myFile.txt than this,
import java.io.File
val resolvedPath = path.split(File.separator).map{ s =>
if (s.startsWith("$")) sys.env(s.drop(1))
else s }.
mkString(File.separator)
val res = io.Source.fromFile(resolvedPath).getLines
The way you have seems good to me, but if you are so inclined or need to do something quickly, you could use Process to get the return of executing a bash command:
import scala.sys.process._
val cleanedPath = Seq("bash", "-c", "echo " + path).!!.trim
You can even use this idea to read the file if you want:
val text = Seq("echo", "-c", "cat " + path).!!
One difference between these and your code is that your code will throw an exception if an environment variable is missing, while bash returns an empty string for that variable. If you wish to mimic that, you could use sys.env.get(s.tail).getOrElse("") instead of sys.env(s.drop(1)) or use the dictionary val myEnv = sys.env.withDefaultValue("").
See System.getenv(). You'll be able to find the variables and replace them with the value to resolve your path.
I' m trying to import a .so library into a python code to use c functions. I think using
from ctypes import *
import ctypes
lib = CDLL('./libcaenhvwrapper.so.5.56')
is working fine. I need to use some user defined types which are defined in a header file
but I cannot access them.
thank you in advance
The types are not in the .so file that the ctypes module loads.
C types don't work like that, they're declared in the header and you must have the header to use a (C) library, even from C.
You're going to have to use the various ctypes APIs to re-create the types in Python. See this part of the tutorial, for instance, for how to work with struct and union types.
Now my code works with a normal c library, but I need to use a .so library from Caen and I
get Segmentation fault. This is the code:
from ctypes import *
lib = CDLL('./libcaenhvwrapper.so.5.56')
lib.CAENHVInitSystem.restype = c_int
lib.CAENHVInitSystem.argtypes = [c_int, c_int, c_char_p, c_char_p, c_char_p]
lib.CAENHVGetError.restype = c_int
CAENHV_SYSTEM_TYPE_t = c_int
sy1527 = CAENHV_SYSTEM_TYPE_t(0)
sy2527 = CAENHV_SYSTEM_TYPE_t(1)
sy4527 = CAENHV_SYSTEM_TYPE_t(2)
sy5527 = CAENHV_SYSTEM_TYPE_t(3)
n568 = CAENHV_SYSTEM_TYPE_t(4)
v65xx = CAENHV_SYSTEM_TYPE_t(5)
n1470 = CAENHV_SYSTEM_TYPE_t(6)
v8100 = CAENHV_SYSTEM_TYPE_t(7)
link = c_int
LINKTYPE_TCPIP = link(0)
LINKTYPE_RS232 = link(1)
LINKTYPE_CAENET = link(2)
LINKTYPE_USB = link(3)
LINKTYPE_OPTLINK = link(4)
LINKTYPE_USB_VCP = link(5)
string15=c_char*15
address=string15('1','3','7','.','1','3','8','.','1','3','.','2','0','3','\0')
userName = c_char_p('user')
passwd = c_char_p('user')
ret_init = lib.CAENHVInitSystem(0, 0, address, userName, passwd)
when I try to call the function I get a segmentation fault. I think the types are correctly defined.
Below you can see a piece of code which works ok.
from ctypes import *
lib2 = CDLL('/lib64/libc.so.6')
string15=c_char*15
address=string15('1','3','7','.','1','3','8','.','1','3','.','2','0','3','\0')
address1=create_string_buffer('137.138.13.203')
address2=c_char_p('137.138.13.200')
userName = c_char_p('user')
passwd = c_char_p('user')
a= lib2.strncmp(address, userName, c_int(4))
a= lib2.strncmp(userName, address, 4)
a= lib2.strncmp(address2, address, 15)
lib2.printf('%d\n', ret_init)
lib2.printf('%s\n', address)
lib2.printf('%s\n', address1)
lib2.printf('%s\n', address2)
lib2.printf('%d\n', lib2.strlen(address))
lib2.printf('%d\n', lib2.strlen(address1))
lib2.printf('%d\n', lib2.strlen(address2))
I have converted around 90+ fortran files into C files using a tool and I need to validate that the conversion is good or not.
Can you give me some ideas on how best to ensure that the functionality has been preserved through the translation?
You need verification tests that exercise those fortran functions. Then you run those tests against the c code.
You can use unit test technology/methodology. In fact I can't see how else you would prove that the conversion is correct.
In lots of unit test methodologies you would write the tests in the same language as the code, but in this case I recommend very very strongly to pick one language and one code base to exercise both sets of functions. Also don't worry about be trying to create pure unit tests rather use the techniques to give you coverage of all the use that the fortran code was supposed to handle.
Use unit tests.
First write your unit tests on the Fortran code and check whether they all run correctly, then rewrite them in C and run those.
The problem in this approach is that you also need to rewrite your unit test, which you normally don't do when refactoring code (except for API changes). This means that you might end up debugging your ported unit testing code as well, beside the actual code.
Therefore, it might be better to write testing code that contains minimal logic and only write the results of the functions to a file. Then you can rewrite this minimal testing code in C, generate the same files and compare the files.
Here is what I did for a "similar" task (comparing fortran 90 to fortran 90 + OpenACC GPU accelerated code):
Analyze what's the output of each Fortran module.
Write these output arrays to .dat files.
Copy the .dat files into a reference folder.
Write the output of the converted modules to files (either CSV or binary). Use the same filename for convenience.
Make a python script that compares the two versions.
I used convenience functions like these in fortran (analogous for 1D, 2D case):
subroutine write3DToFile(path, array, n1, n2, n3)
use pp_vardef
use pp_service, only: find_new_mt
implicit none
!input arguments
real(kind = r_size), intent(in) :: array(n1,n2,n3)
character(len=*), intent(in) :: path
integer(4) :: n1
integer(4) :: n2
integer(4) :: n3
!temporary
integer(4) :: imt
call find_new_mt(imt)
open(imt, file = path, form = 'unformatted', status = 'replace')
write(imt) array
close(imt)
end subroutine write3DToFile
In python I used the following script for reading binary Fortran data and comparing it. Note: Since you want to convert to C you would have to adapt it such that you can read the data produced by C instead of Fortran.
from optparse import OptionParser
import struct
import sys
import math
def unpackNextRecord(file, readEndianFormat, numOfBytesPerValue):
header = file.read(4)
if (len(header) != 4):
#we have reached the end of the file
return None
headerFormat = '%si' %(readEndianFormat)
headerUnpacked = struct.unpack(headerFormat, header)
recordByteLength = headerUnpacked[0]
if (recordByteLength % numOfBytesPerValue != 0):
raise Exception, "Odd record length."
return None
recordLength = recordByteLength / numOfBytesPerValue
data = file.read(recordByteLength)
if (len(data) != recordByteLength):
raise Exception, "Could not read %i bytes as expected. Only %i bytes read." %(recordByteLength, len(data))
return None
trailer = file.read(4)
if (len(trailer) != 4):
raise Exception, "Could not read trailer."
return None
trailerUnpacked = struct.unpack(headerFormat, trailer)
redundantRecordLength = trailerUnpacked[0]
if (recordByteLength != redundantRecordLength):
raise Exception, "Header and trailer do not match."
return None
dataFormat = '%s%i%s' %(readEndianFormat, recordLength, typeSpecifier)
return struct.unpack(dataFormat, data)
def rootMeanSquareDeviation(tup, tupRef):
err = 0.0
i = 0
for val in tup:
err = err + (val - tupRef[i])**2
i = i + 1
return math.sqrt(err)
##################### MAIN ##############################
#get all program arguments
parser = OptionParser()
parser.add_option("-f", "--file", dest="inFile",
help="read from FILE", metavar="FILE", default="in.dat")
parser.add_option("--reference", dest="refFile",
help="reference FILE", metavar="FILE", default="ref.dat")
parser.add_option("-b", "--bytesPerValue", dest="bytes", default="4")
parser.add_option("-r", "--readEndian", dest="readEndian", default="big")
parser.add_option("-v", action="store_true", dest="verbose")
(options, args) = parser.parse_args()
numOfBytesPerValue = int(options.bytes)
if (numOfBytesPerValue != 4 and numOfBytesPerValue != 8):
print "Unsupported number of bytes per value specified."
sys.exit()
typeSpecifier = 'f'
if (numOfBytesPerValue == 8):
typeSpecifier = 'd'
readEndianFormat = '>'
if (options.readEndian == "little"):
readEndianFormat = '<'
inFile = None
refFile = None
try:
#prepare files
inFile = open(str(options.inFile),'r')
refFile = open(str(options.refFile),'r')
i = 0
while True:
passedStr = "pass"
i = i + 1
unpackedRef = None
try:
unpackedRef = unpackNextRecord(refFile, readEndianFormat, numOfBytesPerValue)
except(Exception), e:
print "Error reading record %i from %s: %s" %(i, str(options.refFile), e)
sys.exit()
if (unpackedRef == None):
break;
unpacked = None
try:
unpacked = unpackNextRecord(inFile, readEndianFormat, numOfBytesPerValue)
except(Exception), e:
print "Error reading record %i from %s: %s" %(i, str(options.inFile), e)
sys.exit()
if (unpacked == None):
print "Error in %s: Record expected, could not load record it" %(str(options.inFile))
sys.exit()
if (len(unpacked) != len(unpackedRef)):
print "Error in %s: Record %i does not have same length as reference" %(str(options.inFile), i)
sys.exit()
#analyse unpacked data
err = rootMeanSquareDeviation(unpacked, unpackedRef)
if (abs(err) > 1E-08):
passedStr = "FAIL <-------"
print "%s, record %i: Mean square error: %e; %s" %(options.inFile, i, err, passedStr)
if (options.verbose):
print unpacked
except(Exception), e:
print "Error: %s" %(e)
finally:
#cleanup
if inFile != None:
inFile.close()
if refFile != None:
refFile.close()