ctypes, error when calling function

Discussion in 'Python' started by Max M, Oct 7, 2004.

  1. Max M

    Max M Guest

    Trying to write realtime midi in Windows I am using ctypes. So I have
    written a small wrapper for winmm.dll

    It partly works. I get this error when I try to run it:

    Traceback (most recent call last):
    File "E:\maxm\pys\MIDI-R~1\x.py", line 203, in ?
    print winmm.midiOutGetDevCaps(deviceID, caps, sizeof(caps))
    File "E:\maxm\pys\MIDI-R~1\x.py", line 133, in __getattr__
    return getattr(self._winmm, attr)
    File "C:\pytyons\Python23\Lib\site-packages\ctypes\__init__.py", line
    316, in __getattr__
    func = self._StdcallFuncPtr(name, self)
    AttributeError: function 'midiOutGetDevCaps' not found

    But the documentation says that the midiOutGetDevCaps() should exist in
    the dll.

    It calls the midiOutGetNumDevs() function in the dll nicely, wich is why
    I find it to be strange problem.

    Does anybody have a clue? It's my first try at ctypes, so I am a bit
    lost here.

    regards Max M


    #################################3
    # The code

    from ctypes import *

    MAXPNAMELEN = 32

    class MIDIOUTCAPS(Structure):
    _fields_ = [
    ("wMid", c_int), # WORD
    ("wPid", c_int), # WORD
    ("vDriverVersion", c_long), # MMVERSION
    ("szPname", c_char * MAXPNAMELEN), # CHAR
    ("wTechnology", c_int), # WORD
    ("wVoices", c_int), # WORD
    ("wNotes", c_int), # WORD
    ("wChannelMask", c_int), # WORD
    ("dwSupport", c_long), # DWORD
    ]


    class Winmm:

    """A *very* thin wrapper over WINMM.DLL :)
    """

    def __init__(self):
    self._winmm = windll.WINMM

    def __getattr__(self, attr):
    return getattr(self._winmm, attr)



    if __name__ == '__main__':

    caps = MIDIOUTCAPS()
    winmm = Winmm()
    numDevs = winmm.midiOutGetNumDevs()
    for deviceID in range(-1, numDevs):
    print winmm.midiOutGetDevCaps(deviceID, caps, sizeof(caps))






    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
    Max M, Oct 7, 2004
    #1
    1. Advertising


  2. > AttributeError: function 'midiOutGetDevCaps' not found


    Like a lot of Windows APIs, midiOutGetDevCaps exists in both ANSI and
    Unicode variants. You need to call midiOutGetDevCapsA or
    midiOutGetDevCapsW according to whether you're using ANSI or Unicode.

    Because you're using c_char in your MIDIOUTCAPS structure:

    > ("szPname", c_char * MAXPNAMELEN)


    you need to call the ANSI variant, midiOutGetDevCapsA.

    When you're programming Windows in C, the API header files define
    midiOutGetDevCaps to be either midiOutGetDevCapsA or midiOutGetDevCapsW
    according to whether you're compiling an ANSI or Unicode application.
    This is why any C-based sample code you might see doesn't have this
    problem.

    --
    Richie Hindle
    Richie Hindle, Oct 7, 2004
    #2
    1. Advertising

  3. Max M

    Max M Guest

    Richie Hindle wrote:
    >>AttributeError: function 'midiOutGetDevCaps' not found

    >
    > Like a lot of Windows APIs, midiOutGetDevCaps exists in both ANSI and
    > Unicode variants. You need to call midiOutGetDevCapsA or
    > midiOutGetDevCapsW according to whether you're using ANSI or Unicode.


    Ah, ok. That nailed it.

    > Because you're using c_char in your MIDIOUTCAPS structure:


    Now I only need to get my MIDIOUTCAPS structure correct.

    ValueError: Procedure probably called with too many arguments (60 bytes
    in excess)

    But I can probably figure that out myself.

    thanks!

    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
    Max M, Oct 7, 2004
    #3
  4. [Max]
    > caps = MIDIOUTCAPS()
    > [...]
    > print winmm.midiOutGetDevCapsA(deviceID, caps, sizeof(caps))
    > [...]
    > ValueError: Procedure probably called with too many arguments (60 bytes
    > in excess)


    You need to pass byref(caps) rather than caps. The API expects a
    pointer to the structure, not the structure itself.

    --
    Richie Hindle
    Richie Hindle, Oct 7, 2004
    #4
  5. Max M

    Max M Guest

    Richie Hindle wrote:
    > [Max]
    >
    >>caps = MIDIOUTCAPS()
    >>[...]
    >>print winmm.midiOutGetDevCapsA(deviceID, caps, sizeof(caps))
    >>[...]
    >>ValueError: Procedure probably called with too many arguments (60 bytes
    >>in excess)

    >
    >
    > You need to pass byref(caps) rather than caps. The API expects a
    > pointer to the structure, not the structure itself.


    Thanks. Yes I figured it out about the same time i read your reply.

    I guess it's been about 15 years since I have last coded in c, :-s so
    I'm a bit rusty.

    --

    hilsen/regards Max M, Denmark

    http://www.mxm.dk/
    IT's Mad Science
    Max M, Oct 7, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andreas Lagemann
    Replies:
    8
    Views:
    452
    Mike Wahler
    Jan 10, 2005
  2. tiwy
    Replies:
    0
    Views:
    423
  3. Todd Gardner
    Replies:
    3
    Views:
    436
    Myles
    Jan 14, 2004
  4. Henk Punt
    Replies:
    0
    Views:
    385
    Henk Punt
    Jul 23, 2004
  5. Replies:
    0
    Views:
    486
Loading...

Share This Page