Re: How to pass String BYREF to C function?
Andrew Wilson <[email protected]>
| Newsgroups | gmane.comp.python.ctypes |
|---|---|
| Message-ID | <[email protected]> |
Hey Lynton, Your c code needs to properly terminate the string with a '\n' in order for python to print the result correctly. Andrew On Wed, Aug 18, 2010 at 8:11 AM, Lynton Grice <[email protected]>wrote: > Hi Andrew, > > > > Thanks for the help on this, great stuff. > > > > If I run the code from a C client I will get “half the first string”.... > > > > If I print out the “exitResult” like you specified below: > > > > print ctypes.c_char_p(exitResult.value).value > > > > I get the following output in WingIDE > > > > helloö > > > > So it works but what are those funny characters at the end of the string? > It is not serious though, I am just curious... > > > > Do I need to change my C code to get rid of those funny characters? > > > > int executeUserExit(char *buffer, char **userExitResultBuffer){ > > int total_len; > > > > total_len = strlen(buffer) / 2; > > *userExitResultBuffer = (char*) malloc(total_len); > > strncpy(*userExitResultBuffer, buffer, total_len); > > return 0; > > } > > > > Thanks again > > > > Lynton > > > > *From:* [email protected] [mailto:[email protected]] *On > Behalf Of *Andrew Wilson > *Sent:* 18 August 2010 02:00 PM > *To:* Lynton Grice > *Cc:* [email protected]; [email protected] > > *Subject:* Re: [ctypes-users] How to pass String BYREF to C function? > > > > Lynton, > The following code is a hack; keep in mind that python strings are > immutable so your c_char_p variables can't be written to by the dll. > Instead you should be using "create_string_buffer" for writeable strings. I > wasn't so sure about the char** variable so I just made it an int pointer > and then cast it back to a string once the result were in. > > > import ctypes > import os > > if __name__ == "__main__": > if os.name=='nt': > userExit = ctypes.cdll.LoadLibrary("libUserExits.dll") > executeUserExit = userExit.executeUserExit > > stream = ctypes.create_string_buffer("hello world") > exitResult = ctypes.c_uint(0) > result = executeUserExit(stream, ctypes.byref(exitResult)) > print result, stream.value, ctypes.c_char_p(exitResult.value).value > print "Finished" > > > > > > > > > > > > > > > > > > > > > On Wed, Aug 18, 2010 at 4:24 AM, Lynton Grice < > [email protected]> wrote: > > Hi there, > > > > Thanks for the comments. Please note that this is just a test script so I > am not fussed about the “os.name”....I can take all that extra out > later....I just wanted to get it working for now. > > > > I tried out something like what you said but still no luck: > > > > import ctypes as c > > > > userExit = c.cdll.LoadLibrary("libUserExits.dll") > > executeUserExit = userExit.executeUserExit > > executeUserExit.argtypes = [c.c_char_p, c.POINTER(c.c_char_p)] > > executeUserExit.restype = c.c_int > > stream = (c.c_char * 20)(*list("hello world")) > > exitResult = c.c_char_p() > > result = executeUserExit(c.byref(stream), c.byref(exitResult)) > > print result > > print "Finished" > > > > > > I will keep trying with a couple options...thanks for the push in the right > direction though, much appreciated > > > > Lynton > > > > *From:* [email protected] [mailto:[email protected]] > *Sent:* 18 August 2010 09:46 AM > > > *To:* Lynton Grice > *Subject:* Re: [ctypes-users] How to pass String BYREF to C function? > > > > > > On Aug 17, 2010, at 8:08 PM, Lynton Grice wrote: > > > > Hi there, > > > > I have the following example C function that basically take 2 arguments and > “halves the first string” and puts that result in the second argument. > > > > int executeUserExit(char *buffer, char **userExitResultBuffer){ > > int total_len; > > > > total_len = strlen(buffer) / 2; > > *userExitResultBuffer = (char*) malloc(total_len); > > strncpy(*userExitResultBuffer, buffer, total_len); > > return 0; > > } > > > > I have call this from C code happily, but am having trouble from Python. > > > > I created a DLL from the code above > > > > import ctypes as c > > import os > > > > if __name__ == "__main__": > > if os.name=='nt': > > userExit = c.cdll.LoadLibrary("libUserExits.dll") > > executeUserExit = userExit.executeUserExit > > executeUserExit.argtypes = [c.c_char_p, c.c_char_p] > > executeUserExit.restype = c.c_int > > stream = c.c_char_p() > > stream.value = "hello world" > > exitResult = c.c_char_p() > > result = executeUserExit(c.pointer(stream), > c.byref(exitResult)) > > print result > > > > print "Finished" > > > > > > > > There is a lot wrong with this on a pure python-level. Please think of why > you use __name__ == "__main__" and os.name for a script you clearly don't > use somewhere else. > > > > But that's just a remark. > > > > The important thing here is that you have to create *arrays* of characters, > the same as with C. Then you can create pointers or byref references for > this. > > > > Something like this (untested): > > > > a = (c_char * 20)(*list("foobarbaz")) > > b = c_char_p() > > result = executeUserExit(byref(a), byref(b)) > > > > > > And of course the declaration of executeUserExit is wrong, you need > argtypes to be [c.c_char_p, POINTER(c.c_char_p)] > > > > Diez > > > > ------------------------------------------------------------------------------ > This SF.net email is sponsored by > > Make an app they can't live without > Enter the BlackBerry Developer Challenge > http://p.sf.net/sfu/RIM-dev2dev > _______________________________________________ > ctypes-users mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/ctypes-users > > > ------------------------------------------------------------------------------ This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev _______________________________________________ ctypes-users mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ctypes-users