hanzac | 2 Feb 12:06 2003

Re: Hi, I have used ctypes and it is great b...

Hi, T. Heller,

Thank you for your detailed direction of how to implement an object from a specified mem address. And I tried
in your way, but...
I found another problem, when I change the c_int object's value, the original target doesn't change at all:

>>> a = 100
>>> i = c_int.from_address(id(a))
>>> ctypes.addressof(i)
16083900
>>> id(a)
16083900
>>> i.value = 2003
>>> a
100
>>> i
c_int(2003)

Maybe the Python memory address is not real, just virtual? and we can't affect it?
I'm getting comfused...

PS: I get another idea that we can  use the memory functions of clib to realize it?
Because I just want to the data on a ddraw surface.
 				
    Sorry to bother you again,
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Hanzac Chen

Hi, T. Heller, (Continue reading)

Brandon Philips | 3 Feb 02:46 2003
Picon

Using my dll

Hello All,
 
Really simple question (I think).
I have compiled some code in C++ as a dll.  I tested it with a simple test program and it does what it is supposed to.  I have played with the Ctypes module and I can call kernel32 functions and etc like are in the examples but I cannot call my dll functions... how do I go about doing that? (I am not a python developer, I am doing this because my group wants my software to be scriptable.)
 
I am using ActivePython 2.2, and have gone to the path that contains my dll and typed python at the command prompt.  I then do the following:
 

C:\Documents and Settings\brandon\My Documents\My Bob Documents\CVSROOT\ninebutt
on\Debug>python
ActivePython 2.2.2 Build 224 (ActiveState Corp.) based on
Python 2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import windll, cdll
>>> cdll.ninebutton.writePacket(1,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "C:\Python22\Lib\site-packages\ctypes.py", line 126, in __getattr__
    func = _DynFunction(name, self, FUNCFLAG_CDECL)
ValueError: function 'writePacket' not found
>>>
 
ninebutton.dll is my dll and writePacket(int, int) is my function.  What did I do wrong?
 
Brandon Philips
Jimmy Retzlaff | 3 Feb 07:42 2003

RE: Using my dll

Brandon Philips [brandon <at> sporknet.cjb.net] wrote:
> Really simple question (I think). I have compiled some code in C++ as a
> dll.
...
> >>> from ctypes import windll, cdll
> >>> cdll.ninebutton.writePacket(1,3)
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
>  File "C:\Python22\Lib\site-packages\ctypes.py", line 126, in __getattr__
>    func = _DynFunction(name, self, FUNCFLAG_CDECL)
> ValueError: function 'writePacket' not found
> 
> ninebutton.dll is my dll and writePacket(int, int) is my function.  What
> did I do wrong?

I would guess you are running up against name mangling. Essentially, if you didn't specify any "custom
linkage" for your writePacket function then there is actually no function called "writePacket" in your
dll. C++ compilers add characters to function names - these characters specify the argument types that
the function accepts. This is how function overloading is implemented. Different C++ compilers (and
sometimes different version of the same compiler) mangle names in different ways so it's not always a good
idea to try to figure out the mangled name and use that.

There are a few ways to turn off name mangling. One is to create a .def file and specify your functions in there
(look in the docs to see how to export functions in a def - it's been a while since I've done it).

Another way is to specify 'extern "C"' linkage. You can do this for one function at a time in your header file
with something like:

extern "C" int coolFunction(int a, int b);

or you can do a whole group of functions by doing something like:

extern "C" {
int coolFunction1(int a, int b);
int coolFunction2(int a, int b, int c);
}

Note that you cannot use function overloading on functions where name mangling is disabled. If you look in
the Windows header files you'll see extern "C" linkage specified. This is actually for the opposite
problem. When calling non-C++ dlls from C++, you don't want C++ looking for mangled names.

Jimmy

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Thomas Heller | 3 Feb 11:18 2003
Picon

Accessing integers at certain memory locations

> Hi, T. Heller,
> 
> Thank you for your detailed direction of how to implement an object
> from a specified mem address. And I tried in your way, but...
> 
> I found another problem, when I change the c_int object's value, the
> original target doesn't change at all:
>  
>  >>> a = 100
>  >>> i = c_int.from_address(id(a))
>  >>> ctypes.addressof(i)
>  16083900
>  >>> id(a)
>  16083900
>  >>> i.value = 2003
>  >>> a
>  100
>  >>> i
>  c_int(2003)
>  
>  Maybe the Python memory address is not real, just virtual? and we can't affect it?
>  I'm getting comfused...

>  PS: I get another idea that we can  use the memory functions of clib to realize it?
>  Because I just want to the data on a ddraw surface.
>   				
>      Sorry to bother you again,
>  ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Hanzac Chen

Hanzac,

maybe my idea to use Python objects for this wasn't so good.

In fact, id(obj) returns the address where a Python object is stored.
Looking through the Python header files, the layout (slightly simplified)
for a Python integer is this:

typedef struct {
    int ob_refcnt;
    struct typeobject *ob_type;
    long ob_ival;
} PyIntObject;

So, id(object) points to this structure if object is a Python integer,
and the first field is an int stored there is the reference count, the
second field is a pointer to the type object, and the third field is
the integer's value.

Since Python integers are immutable, the value 'ob_ival' doesn't change.
So, changing the value with ctypes isn't a good idea, but it's possible
anyway:

  >>> from ctypes import *
  >>> i = 42
  >>> pi = c_int.from_address(id(i)+8)

id(i) + 8 is the address of the ob_ival field:

  >>> print pi
  c_int(42)

and we *can* change it, although we shouldn't do it:

  >>> pi.value = 99
  >>> print 42
  99
  >>> print 42 + 5
  104

Better end Python after this experiment!

Thomas

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Hanzac Chen | 5 Feb 13:32 2003
Picon

Re: Accessing integers at certain memory locations

Thomas,

hehe, I've learned a lot & I'm sorry for keeping the mind of "C".
I found that I began to like exploring the inner implementation. :)thanks

BTW, I have another problem:

When I want to create a Structure & it have a anonymous Union(or Struct), I 
found 
it is hard to realize it. Will you implement the feature?

I am also looking forward to your next version of ctypes.

Hanzac

_________________________________________________________________
享用世界上最大的电子邮件系统— MSN Hotmail。  http://www.hotmail.com  

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Thomas Heller | 5 Feb 14:10 2003
Picon

Re: Accessing integers at certain memory locations

"Hanzac Chen" <hanzac <at> hotmail.com> writes:

> Thomas,
> 
> hehe, I've learned a lot & I'm sorry for keeping the mind of "C".

Well, a certain mind of "C" is probably needed to use ctypes ;-).

> I found that I began to like exploring the inner implementation. :)thanks
> 
> BTW, I have another problem:
> 
> When I want to create a Structure & it have a anonymous Union(or
> Struct), I found it is hard to realize it. Will you implement the
> feature?
> 

Anonymous structures or unions are not (yet) supported, and I have
doubts I want to implement them, because there's an easy workaround:
Just fetch a name and use it.  I also have the impression from looking
at C header files, that not all compilers support them.

Taking VARIANT as an example, this is how I defined it in the samples
(this definition is neither complete nor correct, but I hope you get
the impression):

class VARIANT(Structure):
    class U(Union):
        _fields_ = [("bVal", "b"),      # VT_UI1
                    ("iVal", "h"),      # VT_I2
                    ("lVal", "l"),      # VT_I4
                    ("fltVal", "f"),    # VT_R4
                    ("dblVal", "d"),    # VT_R8
                    ("boolVal", "i"),   # VT_BOOL
                    ("scode", "i"),     # VT_ERROR
                    ("pdispVal", IDispatchPointer), # VT_DISPATCH
                    ("punkVal", IUnknownPointer), # VT_UNKNOWN
                    ("bstrVal", "i"),
                    ("myBstrVal", "Z"),
                    ("uiVal", "H"),     # VT_UI2
                    ("ulVal", "L"),     # VT_UI4
                    ("intVal", "i"),    # VT_INT
                    ("uintVal", "I"),   # VT_UINT
                    ]

    _fields_ = [("vt", "h"),
                ("wReserved1", "h"),
                ("wReserved2", "h"),
                ("wReserved3", "h"),
                ("u", U)]

So, you have to write

v = VARIANT()
v.u.bVal

instead of

v.bVal

You could also use '_' as the name for the anonymous part,
and then write

v._.bVal instead if you prefer.

> 
> I am also looking forward to your next version of ctypes.

I'm still fixing a lot of bugs, and writing unittests.
But as I said before, it there is a need for a snapshot
I can create one.

> 
> Hanzac
> 

Thomas

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Niki Spahiev | 5 Feb 14:30 2003
Picon

Re: Accessing integers at certain memory locations

Thomas Heller wrote:
> Anonymous structures or unions are not (yet) supported, and I have
> doubts I want to implement them, because there's an easy workaround:
> Just fetch a name and use it.  I also have the impression from looking
> at C header files, that not all compilers support them.
> 
> Taking VARIANT as an example, this is how I defined it in the samples
> (this definition is neither complete nor correct, but I hope you get
> the impression):
> 
> class VARIANT(Structure):
>     class U(Union):
>         _fields_ = [("bVal", "b"),      # VT_UI1
>                     ("iVal", "h"),      # VT_I2
>                     ("lVal", "l"),      # VT_I4
>                     ("fltVal", "f"),    # VT_R4
>                     ("dblVal", "d"),    # VT_R8
>                     ("boolVal", "i"),   # VT_BOOL
>                     ("scode", "i"),     # VT_ERROR
>                     ("pdispVal", IDispatchPointer), # VT_DISPATCH
>                     ("punkVal", IUnknownPointer), # VT_UNKNOWN
>                     ("bstrVal", "i"),
>                     ("myBstrVal", "Z"),
>                     ("uiVal", "H"),     # VT_UI2
>                     ("ulVal", "L"),     # VT_UI4
>                     ("intVal", "i"),    # VT_INT
>                     ("uintVal", "I"),   # VT_UINT
>                     ]
> 
> 
>     _fields_ = [("vt", "h"),
>                 ("wReserved1", "h"),
>                 ("wReserved2", "h"),
>                 ("wReserved3", "h"),
>                 ("u", U)]
> 

If there is VARIANT._anon_ = 'u' maybe metaclass can generate some magic 
property forwadring e.g.

	def _bVal_get(o):
		return o.u.bVal

HTH
Niki Spahiev

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Hanzac Chen | 7 Feb 04:33 2003
Picon

Re: Accessing integers at certain memory locations

ctypes-usersThomas Heller wrote:
> Anonymous structures or unions are not (yet) supported, and I have
> doubts I want to implement them, because there's an easy workaround:
> Just fetch a name and use it.  I also have the impression from looking
> at C header files, that not all compilers support them.
> 
> Taking VARIANT as an example, this is how I defined it in the samples
> (this definition is neither complete nor correct, but I hope you get
> the impression):

But in this way, the problem is that if I call a dll function and pass an 
object 
of such struct, I wonder the function maybe won't run well.
Why the anonymous union is not easy to realize?

Hanzac 

_________________________________________________________________
享用世界上最大的电子邮件系统— MSN Hotmail。  http://www.hotmail.com  

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
Niki Spahiev | 3 Feb 14:40 2003
Picon

CString_new - no trailing zero

Hello ctypes users!

Just subscried and have bugfix for CString_new. It allocates one more
byte but fails to put zero there. Here is proposed fix.
Same info posted on sf.net patch mamager.

Which is the best place for posting bugs?

regards,
Niki Spahiev

P.S.
Thomas, am i supposed to make new "_pack_" patch?

Index: source/_ctypes.c
===================================================================
RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v
retrieving revision 1.23
diff -u -2 -r1.23 _ctypes.c
--- source/_ctypes.c	31 Jan 2003 19:34:41 -0000	1.23
+++ source/_ctypes.c	3 Feb 2003 13:02:00 -0000
 <at>  <at>  -2290,9 +2293,13  <at>  <at> 
 		obj->b_size = size;
 		obj->b_needsfree = 1;
+		obj->b_ptr[size-1] = 0;	// size is real_size+1
+		memcpy(obj->b_ptr, data, size);
 	}
+	/* data is uninitialized variable when (init == Py_None)
 	if (data)
 		memcpy(obj->b_ptr, data, size);
 	else
 		memset(obj->b_ptr, 0, size);
+	*/

 	return (PyObject *)obj;

Thomas Heller | 3 Feb 15:48 2003
Picon

Re: CString_new - no trailing zero

Niki Spahiev <niki <at> vintech.bg> writes:

> Hello ctypes users!
> 
> Just subscried and have bugfix for CString_new. It allocates one more
> byte but fails to put zero there. Here is proposed fix.
> Same info posted on sf.net patch mamager.
> 
> Which is the best place for posting bugs?

As usual, posting to the bug/patch tracker on sourceforge does prevent
that bugs are forgotten.

> Index: source/_ctypes.c
> ===================================================================
> RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v
> retrieving revision 1.23
> diff -u -2 -r1.23 _ctypes.c
> --- source/_ctypes.c	31 Jan 2003 19:34:41 -0000	1.23
> +++ source/_ctypes.c	3 Feb 2003 13:02:00 -0000
>  <at>  <at>  -2290,9 +2293,13  <at>  <at> 
>  		obj->b_size = size;
>  		obj->b_needsfree = 1;
> +		obj->b_ptr[size-1] = 0;	// size is real_size+1
> +		memcpy(obj->b_ptr, data, size);
>  	}

size is already the length of the init Python string '+ 1', so it
includes the trailing NUL character, and it *will* be copied by the
memcpy call.

> +	/* data is uninitialized variable when (init == Py_None)
>  	if (data)
>  		memcpy(obj->b_ptr, data, size);
>  	else
>  		memset(obj->b_ptr, 0, size);
> +	*/
>  
>  	return (PyObject *)obj;

You're right, this code looks strange, and indeed passes in invalid
pointer to memcpy.  On the other hand, it can only happen when size is
0, so memcpy doesn't access this pointer ;-).

But I've changed the code to be clearer.  Thanks for the patch!

> 
> regards,
> Niki Spahiev
> 
> P.S.
> Thomas, am i supposed to make new "_pack_" patch?

If you want, go ahead!  Unless you can't wait one or two weeks (not
sure how long exactly) before I'll do it.

Also note that there are now unittest for all and everything (at least
that's the plan), and they would also be required for the packing.

BTW: You will notice there aren't any 'obj->align = -1' calls anymore
in the code.  They meant something like "I'll think about this when I
have time for it" ;-)

Thomas

-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com

Gmane