Re: How to pass String BYREF to C function?

"Lynton Grice" <[email protected]>
Newsgroups gmane.comp.python.ctypes
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.