DLLCC and int8_t problem

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

DLLCC and int8_t problem

Stewart MacLean

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and that VisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Vincent Lesbros-2
it seems that the adress returned by dev->ptr->getPortName(portNumber).data() is not valid after the call of the function.
I think you shoud allocate memory in the heap from smalltalk, pass the buffer to the c function,
make a copy (strcpy) from the C, instead of returning a CONST char * 






2014/1/11 Stewart MacLean <[hidden email]>

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and that VisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc



_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Stewart MacLean

Hi Vincent,

 

Thanks for your reply. I

 

I haven’t had a chance to try your suggestion as yet, but within the C routine I:

 

1)       Assign the result of dev->ptr->getPortName(portNumber).data() to a local variable and write it to standard out – the value being the same I get in Smalltalk “H”.

2)       Write the dev->ptr->getPortName(portNumber).data() directly to standard out, and I get the expected result.

 

This implies that the address is valid after the call of the function as it is able to be written to standard out. And the effect of assigning it to a local variable is the same as what is happening when I return the pointer to Smalltalk.

 

I believe other functions successfully return pointers, so I’m not really sure what is going on here.

 

Thanks,

 

Stewart

 

-----Original Message-----
From: Vincent Lesbros [mailto:[hidden email]]
Sent: 11 January 2014 10:42 p.m.
To: [hidden email]
Cc: [hidden email]
Subject: Re: [vwnc] DLLCC and int8_t problem

 

it seems that the adress returned by dev->ptr->getPortName(portNumber).data() is not valid after the call of the function.

I think you shoud allocate memory in the heap from smalltalk, pass the buffer to the c function,

make a copy (strcpy) from the C, instead of returning a CONST char * 

 

 

 

 

 

2014/1/11 Stewart MacLean <[hidden email]>

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and that VisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Michael Lucas-Smith-2
In reply to this post by Stewart MacLean
Hi Stewart,

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

I could be completely wrong about this though :)

Cheers,
Michael

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:

Hi,
 
I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.
 
I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.
 
I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.
 
This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.
 
Any suggestions as to how to fix this very much appreciated.
 
Thanks,
 
Stewart
 
Console Output:
=============
getOutPortName Charxxx
0
name:
H
dev->ptr->getPortName(portNumber).data():
Microsoft GS Wavetable Synth
getOutPortName Charxxx
1
name:
H
dev->ptr->getPortName(portNumber).data():
LoopBe Internal MIDI
 
Transcript output:
==============
Raw value: a CPointer {029861A0} (const char * )
copyCStringFromHeap: H
Raw value: a CPointer {029861A0} (const char * )
copyCStringFromHeap: H
In:
            0: H
 
Out:
            0: H
            1: H
 
C Function:
==========
 
const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){
     try { std::cout << "getOutPortName Charxxx\n";
                        std::cout << portNumber;
                        std::cout << "\n";
                        const char* name = dev->ptr->getPortName(portNumber).data();
                        std::cout <<"name: \n";
                        std::cout << name;
                        std::cout << "\n";
                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";
                        std::cout << dev->ptr->getPortName(portNumber).data();
                        std::cout << "\n";
                        return (const char*)dev->ptr->getPortName(portNumber).data();
                        // const char* literal = "literal NAME!!!!";
                        // return (const char*)literal;
     }
     catch ( RtError &error ) {
          error.printMessage();
          char* name = "no name";
          return (const char*)name;
     }
};
 
 
_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Stewart MacLean

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent:
13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:



Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Wallen, David

Offhand, it looks like you’re loading a C++ DLL with VisualWorks. Last I looked, VW doesn’t play (on Windows) with C++ DLLs. Your DLL would need to have a special wrapper around the functions to be exported as “C” (not C++) functions. Eg., export extern C {…} or something like that. If this is indeed the problem, the stack won’t contain what you expect going into your function, and the stuff coming out won’t be right either. To get it to work, iirc you need to compile your DLL as a “C” dll (I forget what the incantations are) and do that extern magic in the header around the exported function declarations.

- Dave

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Stewart MacLean
Sent: Monday, January 13, 2014 12:22 AM
To: 'Michael Lucas-Smith'
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent: 13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:



Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Kooyman, Les
If you don't have the source to the DLL to recompile it, in the past I have created a second DLL with the extern "C" definitions and wrappers that redirect to the original C++ DLL.

From: [hidden email] [[hidden email]] on behalf of Wallen, David [[hidden email]]
Sent: Monday, January 13, 2014 10:58 AM
To: [hidden email]
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

Offhand, it looks like you’re loading a C++ DLL with VisualWorks. Last I looked, VW doesn’t play (on Windows) with C++ DLLs. Your DLL would need to have a special wrapper around the functions to be exported as “C” (not C++) functions. Eg., export extern C {…} or something like that. If this is indeed the problem, the stack won’t contain what you expect going into your function, and the stuff coming out won’t be right either. To get it to work, iirc you need to compile your DLL as a “C” dll (I forget what the incantations are) and do that extern magic in the header around the exported function declarations.

- Dave

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Stewart MacLean
Sent: Monday, January 13, 2014 12:22 AM
To: 'Michael Lucas-Smith'
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent: 13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:



Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Stewart MacLean
In reply to this post by Wallen, David

Hi David and Kooyman,

 

You are on the right track here. In fact wrapping C++ with C is what I’m attempting to do:

C++ written by Gary P. Scavone http://www.music.mcgill.ca/~gary/rtmidi/

C wrapper API written by Ben Swift https://github.com/benswift/rtmidi-c-api

I did have to #define DllExport   __declspec( dllexport ) and prefix the functions to get them to appear in the .dll. And the code does include #ifdef __cplusplus

extern "C"  {

#endif

 

I need to figure out if _cplusplus is in fact defined. It appears the .cpp or .c suffix of the source file will make a difference. Some googling and experimentation to do…

 

Thanks,

 

Stewart

 

-----Original Message-----
From: Wallen, David [mailto:[hidden email]]
Sent
:
14 January 2014 7:58 a.m.
To: [hidden email]
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Offhand, it looks like you’re loading a C++ DLL with VisualWorks. Last I looked, VW doesn’t play (on Windows) with C++ DLLs. Your DLL would need to have a special wrapper around the functions to be exported as “C” (not C++) functions. Eg., export extern C {…} or something like that. If this is indeed the problem, the stack won’t contain what you expect going into your function, and the stuff coming out won’t be right either. To get it to work, iirc you need to compile your DLL as a “C” dll (I forget what the incantations are) and do that extern magic in the header around the exported function declarations.

- Dave

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Stewart MacLean
Sent:
Monday, January 13, 2014 12:22 AM
To: 'Michael Lucas-Smith'
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent:
13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:

 

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Wallen, David

Hi Stuart,

 

Yes, it’s not exactly trivial to do, and MS seems to change the required steps every compiler release. It looks like you’re exactly on the right track, going the route suggested by Les. In fact, if you’re using a Windows api, it seems likely that the api’s functions are “C” functions, not C++. When that’s the case, it’s often easiest to create a purely C dLL project, not a C++ dll project. There may still be a compiler/linker setting for that, with luck. If so, presumably you won’t need to make those other adjustments.

 

- Dave

 

From: Stewart MacLean [mailto:[hidden email]]
Sent: Tuesday, January 14, 2014 11:22 AM
To: Wallen, David; Kooyman, Les
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Hi David and Kooyman,

 

You are on the right track here. In fact wrapping C++ with C is what I’m attempting to do:

C++ written by Gary P. Scavone http://www.music.mcgill.ca/~gary/rtmidi/

C wrapper API written by Ben Swift https://github.com/benswift/rtmidi-c-api

I did have to #define DllExport   __declspec( dllexport ) and prefix the functions to get them to appear in the .dll. And the code does include #ifdef __cplusplus

extern "C"  {

#endif

 

I need to figure out if _cplusplus is in fact defined. It appears the .cpp or .c suffix of the source file will make a difference. Some googling and experimentation to do…

 

Thanks,

 

Stewart

 

-----Original Message-----
From: Wallen, David [mailto:[hidden email]]
Sent: 14 January 2014 7:58 a.m.
To: [hidden email]
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Offhand, it looks like you’re loading a C++ DLL with VisualWorks. Last I looked, VW doesn’t play (on Windows) with C++ DLLs. Your DLL would need to have a special wrapper around the functions to be exported as “C” (not C++) functions. Eg., export extern C {…} or something like that. If this is indeed the problem, the stack won’t contain what you expect going into your function, and the stuff coming out won’t be right either. To get it to work, iirc you need to compile your DLL as a “C” dll (I forget what the incantations are) and do that extern magic in the header around the exported function declarations.

- Dave

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Stewart MacLean
Sent: Monday, January 13, 2014 12:22 AM
To: 'Michael Lucas-Smith'
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent: 13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:

 

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: DLLCC and int8_t problem

Stewart MacLean

Hi Dave et al.

 

Well I tried changing the source file suffix and adding the –cplusplus define and ended up with a lot of compiler errors.

 

Unfortunately this will have to wait till I get back from holiday.

 

Thanks for the suggestions,

 

Cheers,

 

Stewart

 

-----Original Message-----
From: Wallen, David [mailto:[hidden email]]
Sent: 15 January 2014 8:34 a.m.
To: [hidden email]; Kooyman, Les
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Hi Stuart,

 

Yes, it’s not exactly trivial to do, and MS seems to change the required steps every compiler release. It looks like you’re exactly on the right track, going the route suggested by Les. In fact, if you’re using a Windows api, it seems likely that the api’s functions are “C” functions, not C++. When that’s the case, it’s often easiest to create a purely C dLL project, not a C++ dll project. There may still be a compiler/linker setting for that, with luck. If so, presumably you won’t need to make those other adjustments.

 

- Dave

 

From: Stewart MacLean [mailto:[hidden email]]
Sent: Tuesday, January 14, 2014 11:22 AM
To: Wallen, David; Kooyman, Les
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Hi David and Kooyman,

 

You are on the right track here. In fact wrapping C++ with C is what I’m attempting to do:

C++ written by Gary P. Scavone http://www.music.mcgill.ca/~gary/rtmidi/

C wrapper API written by Ben Swift https://github.com/benswift/rtmidi-c-api

I did have to #define DllExport   __declspec( dllexport ) and prefix the functions to get them to appear in the .dll. And the code does include #ifdef __cplusplus

extern "C"  {

#endif

 

I need to figure out if _cplusplus is in fact defined. It appears the .cpp or .c suffix of the source file will make a difference. Some googling and experimentation to do…

 

Thanks,

 

Stewart

 

-----Original Message-----
From: Wallen, David [mailto:[hidden email]]
Sent: 14 January 2014 7:58 a.m.
To: [hidden email]
Cc: 'VW NC'
Subject: RE: [vwnc] DLLCC and int8_t problem

 

Offhand, it looks like you’re loading a C++ DLL with VisualWorks. Last I looked, VW doesn’t play (on Windows) with C++ DLLs. Your DLL would need to have a special wrapper around the functions to be exported as “C” (not C++) functions. Eg., export extern C {…} or something like that. If this is indeed the problem, the stack won’t contain what you expect going into your function, and the stuff coming out won’t be right either. To get it to work, iirc you need to compile your DLL as a “C” dll (I forget what the incantations are) and do that extern magic in the header around the exported function declarations.

- Dave

 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Stewart MacLean
Sent: Monday, January 13, 2014 12:22 AM
To: 'Michael Lucas-Smith'
Cc: 'VW NC'
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Michael,

 

As it happens a work colleague suggested the same thing. On checking the C++ routine called there is a switch for UNICODE and it was set in Visual Studio. (please see below).

 

I’ve tried changing it to Not Set and Multi-Byte but this makes no difference, the code below still prints an H.

 

const char* name = dev->ptr->getPortName(portNumber).c_str();

std::cout <<"name: \n";

std::cout << name;

.

Thanks for your suggestions – any others much appreciated!

 

Cheers,

 

Stewart

 

std::string MidiOutWinMM :: getPortName( unsigned int portNumber )

{

  std::string stringName;

  unsigned int nDevices = midiOutGetNumDevs();

  if ( portNumber >= nDevices ) {

    std::ostringstream ost;

    ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid.";

    errorString_ = ost.str();

    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );

    RtMidi::error( RtError::WARNING, errorString_ );

    return stringName;

  }

 

  MIDIOUTCAPS deviceCaps;

  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));

 

#if defined( UNICODE ) || defined( _UNICODE )

  std::cout << "getPortName - UNICODE defined\n";

  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);

  stringName.assign( length, 0 );

  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);

  std::cout << "length " << length << "\n";

#else

  stringName = std::string( deviceCaps.szPname );

  std::cout << "getPortName - UNICODE NOT defined\n";

 

#endif

  std::cout << stringName <<"\n";

  return stringName;

}

 

 

-----Original Message-----
From: Michael Lucas-Smith [mailto:[hidden email]]
Sent: 13 January 2014 3:41 p.m.
To: <[hidden email]>
Cc: VW NC
Subject: Re: [vwnc] DLLCC and int8_t problem

 

Hi Stewart,

 

It’s possible the library is compiled with wide strings, in which case data() will return UTF16 characters, which would mean that ascii characters would be something like 65 0 for an $A. You’ll have to check what kind of encoding the string data is meant to be in. Another point of interest is that calling data() will return the characters, not a c-string, which means it won’t be null-terminated. You could call c_str() instead of data() to ensure it has a null terminator, but that won’t change the width of the characters either.

 

I could be completely wrong about this though :)

 

Cheers,

Michael

 

On 11 Jan 2014, at 4:46 pm, Stewart MacLean <[hidden email]> wrote:

 

Hi,

 

I’m attempting to interface to RtMidi via the RtMidiC-Api using DLLCC. I’ve successfully compiled this on Mac OS X and with some modification to circumvent problems with int64_t got it to work.

 

I’m now working on getting it going on Windows, using VisualStudio 2010 to compile the .DLL. The DLL loads and I can retrieve the port count, but when I go to get the name of a port (which works on Mac OS X, without any modification) I’m not getting the correct values returned. The C function is below. The initial return value was int8_t, but based on the previous problems I’ve had with this in DLLCC, I’ve modified it to be const char* - which is the type returned from the wrapped C++ function.

 

I’m very much a beginner with C, but have added standard output to the console from the dll. I fire up VisualWorks with the console switch. The console output below shows that when I assign the value returned from the C++ function and output it I get the same value the VisualWorks gets “H”. When I output the value returned from the C++ function to the console I get the correct name. If I hard code a return value, that is returned to VisualWorks correctly.

 

This shows that the C++ function is returning the correct value to the C wrapper, and thatVisualWorks is getting receiving literal return values ok, but the assignment to name (within the C function) results in the same value as returned to VisualWorks (once copied from the heap) – this has to be a clue, but I can’t make the connection.

 

Any suggestions as to how to fix this very much appreciated.

 

Thanks,

 

Stewart

 

Console Output:

=============

getOutPortName Charxxx

0

name:

H

dev->ptr->getPortName(portNumber).data():

Microsoft GS Wavetable Synth

getOutPortName Charxxx

1

name:

H

dev->ptr->getPortName(portNumber).data():

LoopBe Internal MIDI

 

Transcript output:

==============

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

Raw value: a CPointer {029861A0} (const char * )

copyCStringFromHeap: H

In:

            0: H

 

Out:

            0: H

            1: H

 

C Function:

==========

 

const char* getOutPortNameChar( outDevice* dev, unsigned int portNumber ){

     try { std::cout << "getOutPortName Charxxx\n";

                        std::cout << portNumber;

                        std::cout << "\n";

                        const char* name = dev->ptr->getPortName(portNumber).data();

                        std::cout <<"name: \n";

                        std::cout << name;

                        std::cout << "\n";

                        std::cout << "dev->ptr->getPortName(portNumber).data(): \n";

                        std::cout << dev->ptr->getPortName(portNumber).data();

                        std::cout << "\n";

                        return (const char*)dev->ptr->getPortName(portNumber).data();

                        // const char* literal = "literal NAME!!!!";

                        // return (const char*)literal;

     }

     catch ( RtError &error ) {

          error.printMessage();

          char* name = "no name";

          return (const char*)name;

     }

};

 

 

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

 


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc