Help with FFI - another try

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

Help with FFI - another try

Eugene Beschastnov
Hi all!

(It looks like my previous message was not properly delivered. Here is
another try.)

Can anybody help me with FFI? I'm trying to use LAME Mp3 Encoder DLL
3.96.1 (lame_enc.dll), but Squeak always crashes.

Here is part of header file of DLL (whole header file,
BladeMP3EncDLL.h, is attached):
=== Start of BladeMP3EncDLL.h =====================================
 #define ATTRIBUTE_PACKED
 #pragma pack(push)
#pragma pack(1)

typedef struct  {
    DWORD   dwConfig;           // BE_CONFIG_XXXXX
                                // Currently only BE_CONFIG_MP3 is supported
    union   {

        struct  {

            DWORD   dwSampleRate;       // 48000, 44100 and 32000 allowed
              BYTE    byMode;         // BE_MP3_MODE_STEREO,
BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
              WORD    wBitrate;       // 32, 40, 48, 56, 64, 80, 96,
112, 128, 160, 192, 224, 256 and 320 allowed
            BOOL    bPrivate;
            BOOL    bCRC;
            BOOL    bCopyright;
            BOOL    bOriginal;

              } mp3;                  // BE_CONFIG_MP3

            struct
              {
            // STRUCTURE INFORMATION
              DWORD           dwStructVersion;
            DWORD           dwStructSize;

              // BASIC ENCODER SETTINGS
            DWORD           dwSampleRate;       // SAMPLERATE OF INPUT FILE
            DWORD           dwReSampleRate;     // DOWNSAMPLERATE,
0=ENCODER DECIDES
              LONG            nMode;              //
BE_MP3_MODE_STEREO, BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO
            DWORD           dwBitrate;          // CBR bitrate, VBR min bitrate
            DWORD           dwMaxBitrate;       // CBR ignored, VBR Max bitrate
              LONG            nPreset;            // Quality preset,
use one of the settings of the LAME_QUALITY_PRESET enum
            DWORD           dwMpegVersion;      // FUTURE USE, MPEG-1 OR MPEG-2
            DWORD           dwPsyModel;         // FUTURE USE, SET TO 0
              DWORD           dwEmphasis;         // FUTURE USE, SET TO 0

            // BIT STREAM SETTINGS
            BOOL            bPrivate;           // Set Private Bit (TRUE/FALSE)
              BOOL            bCRC;               // Insert CRC (TRUE/FALSE)
            BOOL            bCopyright;         // Set Copyright Bit
(TRUE/FALSE)
            BOOL            bOriginal;          // Set Original Bit (TRUE/FALSE)

            // VBR STUFF
            BOOL            bWriteVBRHeader;    // WRITE XING VBR
HEADER (TRUE/FALSE)
            BOOL            bEnableVBR;         // USE VBR ENCODING (TRUE/FALSE)
              INT             nVBRQuality;        // VBR QUALITY 0..9
            DWORD           dwVbrAbr_bps;       // Use ABR in stead of
nVBRQuality
            VBRMETHOD       nVbrMethod;
            BOOL            bNoRes;             // Disable Bit
resorvoir (TRUE/FALSE)

            // MISC SETTINGS
              BOOL            bStrictIso;         // Use strict ISO
encoding rules (TRUE/FALSE)
            WORD            nQuality;           // Quality Setting,
HIGH BYTE should be NOT LOW byte, otherwhise quality=5

            // FUTURE USE, SET TO 0, align strucutre to 331 bytes
              BYTE            btReserved[255-4*sizeof(DWORD) - sizeof( WORD )];

              } LHV1;                 // LAME header version 1

        struct  {

            DWORD   dwSampleRate;
            BYTE    byMode;
            WORD    wBitrate;
            BYTE    byEncodingMethod;

        } aac;

      } format;

} BE_CONFIG, *PBE_CONFIG ATTRIBUTE_PACKED;

__declspec(dllexport) BE_ERR    beInitStream(PBE_CONFIG pbeConfig,
PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream);

#pragma pack(pop)
=== End of BladeMP3EncDLL.h ======================================


Here is what I wrote to correspond DLL header (part of fileout, whole
fileout is attached as LameTest.st). Default values are from
Example.cpp (also attached), which works correct:
=== Start of LameTest.st ===========================================
 ExternalStructure subclass: #BeConfig
    instanceVariableNames: ''
     classVariableNames: ''
    poolDictionaries: ''
    category: 'LameTest'!

!BeConfig methodsFor: 'initialization' stamp: 'epb 6/21/2006 20:36'!
 initialize
    super initialize.
     self
        dwConfig: 256 "BE_CONFIG_LAME";
         format: BeConfigFormat new.! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

BeConfig class
    instanceVariableNames: ''!

!BeConfig class methodsFor: 'as yet unclassified' stamp: 'epb 6/20/2006 21:46'!
 fields
    "self defineFields"
     ^#(
        (dwConfig    'long' "BE_CONFIG_XXXXX. BE_CONFIG_MP3 = 0,
BE_CONFIG_LAME = 256")
         (format      'BeConfigFormat')
    )
 ! !


ExternalStructure subclass: #BeConfigFormat
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'LameTest'!

!BeConfigFormat methodsFor: 'initialization' stamp: 'epb 6/21/2006 20:38'!
 initialize
    super initialize.
     self lhv1: BeConfigLvh1 new.! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

BeConfigFormat class
     instanceVariableNames: ''!

!BeConfigFormat class methodsFor: 'as yet unclassified' stamp: 'epb
6/20/2006 21:44'!
fields
    "self defineFields"
     ^#(
        (lhv1    'BeConfigLvh1')
     )
! !


 ExternalStructure subclass: #BeConfigLvh1
    instanceVariableNames: ''
     classVariableNames: ''
    poolDictionaries: ''
     category: 'LameTest'!

!BeConfigLvh1 methodsFor: 'initialization' stamp: 'epb 6/22/2006 14:37'!
initialize
    super initialize.
     self
        dwStructVersion: 1;
         dwStructSize: 333;
        dwReSampleRate: 0;
        setBeMp3ModeJStereo;
        dwBitrate: 128  "sizeof(beConfig)";
        setPresetR3Mix;
        setMpeg1;
        dwPsyModel: 0;
         dwEmphasis: 0;
        bOriginal: 1;
         bWriteVBRHeader: 1! !


!BeConfigLvh1 methodsFor: 'set parameters' stamp: 'epb 6/21/2006 20:53'!
 setBeMp3ModeJStereo
     self nMode: 1! !

!BeConfigLvh1 methodsFor: 'lame quality presets' stamp: 'epb 6/21/2006 20:57'!
 setPresetR3Mix
    self nPreset: 4! !

 !BeConfigLvh1 methodsFor: 'mpeg version' stamp: 'epb 6/21/2006 21:03'!
setMpeg1
     self dwMpegVersion: 1! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

BeConfigLvh1 class
    instanceVariableNames: ''!

!BeConfigLvh1 class methodsFor: 'as yet unclassified' stamp: 'epb
6/22/2006 14:36'!
 fields
    "self defineFields"
     ^#(
        "STRUCTURE INFORMATION"
        (dwStructVersion     'long')
        (dwStructSize         'long')

         "BASIC ENCODER SETTINGS"
        (dwSampleRate         'long' "SAMPLERATE OF INPUT FILE")
         (dwReSampleRate    'long' "DOWNSAMPLERATE, 0=ENCODER DECIDES")
        (nMode                'long'  "BE_MP3_MODE_STEREO,
BE_MP3_MODE_DUALCHANNEL, BE_MP3_MODE_MONO")
        (dwBitrate            'long'  "CBR bitrate, VBR min bitrate")
         (dwMaxBitrate        'long'  "CBR ignored, VBR Max bitrate")
        (nPreset                'long'  "Quality preset, use one of
the settings of the LAME_QUALITY_PRESET enum")
        (dwMpegVersion        'long'  "FUTURE USE, MPEG-1 OR MPEG-2")
         (dwPsyModel        'long'  "FUTURE USE, SET TO 0")
        (dwEmphasis        'long'  "FUTURE USE, SET TO 0")

        "BIT STREAM SETTINGS"
         (bPrivate            'long'  "Set Private Bit (TRUE/FALSE)")
        (bCRC                'long'  "Insert CRC (TRUE/FALSE)")
        (bCopyright            'long'  "Set Copyright Bit (TRUE/FALSE)")
         (bOriginal            'long'  "Set Original Bit (TRUE/FALSE)")

         "VBR STUFF"
        (bWriteVBRHeader    'long'  "WRITE XING VBR HEADER (TRUE/FALSE)")
         (bEnableVBR        'long'  "USE VBR ENCODING (TRUE/FALSE)")
        (nVBRQuality        'long'  "VBR QUALITY 0..9")
        (dwVbrAbrBps        'long'  "Use ABR in stead of nVBRQuality")
         (nVbrMethod        'long'  "VBR_METHOD_NONE = -1,
VBR_METHOD_DEFAULT =  0, VBR_METHOD_OLD =  1, VBR_METHOD_NEW =  2,
VBR_METHOD_MTRH =  3, VBR_METHOD_ABR =  4")

        (bNoRes                'long'  "Disable Bit resorvoir (TRUE/FALSE)")

         "MISC SETTINGS"
        (bStrictIso            'long'  "Use strict ISO encoding rules
(TRUE/FALSE)")
        (nQuality            'long'  "Quality Setting, HIGH BYTE
should be NOT LOW byte, otherwhise quality=5")

        "FUTURE USE, SET TO 0, align strucutre to 331 bytes"
         (btReserved            'byte' 237  "[255-4*sizeof(DWORD) -
sizeof( WORD )]")
)! !


Object subclass: #LameEncoder
     instanceVariableNames: ''
    classVariableNames: ''
     poolDictionaries: ''
    category: 'LameTest'!

 "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

 LameEncoder class
    instanceVariableNames: ''!

 !LameEncoder class methodsFor: 'api' stamp: 'epb 6/21/2006 21:50'!
apiBeInitStreamBeConfig: beConfig dwSamples: dwSamples dwMp3Buffer:
dwMp3Buffer hbeStream: hbeStream
    <apicall: ulong 'beInitStream' ( BeConfig* long* long* ulong* )
module: 'lame_enc.dll'>
     ^self externalCallFailed! !


 !LameEncoder class methodsFor: 'unit-tests' stamp: 'epb 6/29/2006 15:54'!
testInitStream
 | beConfig errCode dwSamples dwMp3Buffer hbeStream |
beConfig := BeConfig new
     sampleRate: 44100;
    yourself.

 dwSamples := WordArray new: 0.
dwMp3Buffer := WordArray new: 0.
 hbeStream := WordArray new: 0.

errCode := LameEncoder apiBeInitStreamBeConfig: beConfig dwSamples:
dwSamples dwMp3Buffer: dwMp3Buffer hbeStream: hbeStream.

Transcript
    show: 'errCode: '; show: errCode; cr;
    show: 'dwSamples: '; show: dwSamples first; cr;
    show: 'dwMp3Buffer: '; show: dwMp3Buffer first; cr;
    show: 'hbeStream: '; show: hbeStream first; cr.! !
=== End of LameTest.st ===========================================


When I'm executing "LameEncoder testInitStream", Squeak crashes.

Here is stack dump:
=== Start of stack dump ===========================================
---------------------------------------------------------------------
  Fri Jul 14 14:39:58 2006

Exception code: C0000005
  Exception addr: 00427325
Access violation (read access) at 00000480
  EAX:00000480    EBX:88AA1235    ECX:115381B8    EDX:00000481
ESI:00000000    EDI:00520580    EBP:00520580    ESP:0006FB74
  EIP:00427325    EFL:00010282
FP Control: FFFF027F
  FP Status:  FFFF4861
FP Tag:     FFFFFFFF
VM Version: Squeak  3.7.1 (release) from Sep 23 2004
Compiler: gcc 2.95.2 19991024 (release)

  Current byte code: 209
Primitive index: 70

  Loaded plugins:
    lame_enc.dll
      SqueakFFIPrims 23 September 2004 (e)
    LargeIntegers v1.3 23 September 2004 (i)
      Matrix2x3Plugin 23 September 2004 (i)
    FloatArrayPlugin 23 September 2004 (i)
      B2DPlugin 23 September 2004 (i)
    BitBltPlugin 23 September 2004 (i)
      SecurityPlugin 23 September 2004 (i)
    FilePlugin 23 September 2004 (i)
      MiscPrimitivePlugin 23 September 2004 (i)


Stack dump:
=== End of stack dump ===========================================


I tried to call this DLL by many ways, but without success. The best I
did is asking DLL about it's version (beVersion).

Can anybody help?

--
Eugene



BladeMP3EncDLL.h (10K) Download Attachment
LameTest.st (23K) Download Attachment
Example.cpp (10K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

johnmci
On 16-Jul-06, at 11:27 PM, Eugene Beschastnov wrote:
>
>
> dwSamples := WordArray new: 0.
> dwMp3Buffer := WordArray new: 0.
> hbeStream := WordArray new: 0.
>
> errCode := LameEncoder apiBeInitStreamBeConfig: beConfig dwSamples:
> dwSamples dwMp3Buffer: dwMp3Buffer hbeStream: hbeStream.



I'd suspect that setting up these three variables which are going to  
be pointers to store integers into
and asking for 0 bytes of storage to be allocated for each is going  
to be an issue when the DLL attempts
to write 4 bytes into those memory locations.


I'd suggest rather you use
dwSamples := ByteArray new: 4.

and the accessors such as signedLongAt:put:
to access the data, also for the sound data is it big endian or  
little endian? Accessors exist to allow you
choose endian where the choice might not be platform dependent.

Also cross check what the DWORD/BOOL in the software really resolves  
too.

--
========================================================================
===
John M. McIntosh <[hidden email]>
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===



Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
Thanks a lot, John!

"ByteArray new: 4" produces "Could not coerce arguments" error, but
when I'm using "WordArray new: 1" it's OK. Thank you again!

--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
Another question - what construction in Squeak corresponds to PSHORT
in C? I tried ByteArray - Squeak produces error 'Could not coerce
arguments', I tried WordArray - Squeak VM crashes.

--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Bert Freudenberg-3
Am 19.07.2006 um 12:33 schrieb Eugene Beschastnov:

> Another question - what construction in Squeak corresponds to  
> PSHORT in C?

There is no type PSHORT in C. It probably is a typedef (could be a  
macro too) which you need to lookup in the headers.

I'd guess it's a 'short*'.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
I'm not very good in C, but as I understand - yes, it is typedef for
'short*', but it's standard typedef.

Anyway, what kind of data should I use to call FFI function that
expects 'short*'?

To be more specific, C function is
__declspec(dllexport) BE_ERR    beEncodeChunk(HBE_STREAM hbeStream,
DWORD nSamples, PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput);
========================================================
For this function I made this apicall construction:
apiBeEncodeChunkHbeStream: hbeStream nSamples: nSamples pSamples:
pSamples pOutput: pOutput pdwOutput: pdwOutput
    <apicall: ulong 'beEncodeChunk' ( ulong long short* byte* long* )
module: 'lame_enc.dll'>
    ^self externalCallFailed
========================================================
And I'm trying to call it in following way:
        pMp3Buffer := ByteArray new: dwMp3Buffer.
        samples := (SampledSound fromWaveFileNamed: 'Message.wav') asSampledSound
                                samples asWordArray.
        startOfChunk := 1.
        mp3Output := ByteArray new: 0.
        [startOfChunk <= samples size] whileTrue:
                        [endOfChunk := startOfChunk + dwSamples - 1 min: samples size.
                        buf := samples copyFrom: startOfChunk to: endOfChunk.
                        startOfChunk := endOfChunk + 1.
                        pDwWrite := WordArray new: 1.
                        errCode := self
                                                apiBeEncodeChunkHbeStream: hbeStream
                                                nSamples: buf size
                                                pSamples: buf
                                                pOutput: pMp3Buffer
                                                pdwOutput: pDwWrite.
                        errCode ~= self beErrSuccessful
                                ifTrue:
                                        [self apiBeCloseStreamHbeStream: hbeStream.
                                        Exception signal: 'beEncodeChunk() failed (' , errCode asString , ')'].
                        mp3Output addAll: (pMp3Buffer copyFrom: 1 to: pDwWrite first)].
        (FileStream fileNamed: 'Message.mp3') binary
                next: mp3Output size
                putAll: mp3Output
                startingAt: 1

hbeStream, dwSamples and dwMp3Buffer are got from FFI function
'beInitStream', which is called earlier and executed correctly.

2006/7/19, Bert Freudenberg <[hidden email]>:

> Am 19.07.2006 um 12:33 schrieb Eugene Beschastnov:
>
> > Another question - what construction in Squeak corresponds to
> > PSHORT in C?
>
> There is no type PSHORT in C. It probably is a typedef (could be a
> macro too) which you need to lookup in the headers.
>
> I'd guess it's a 'short*'.
>
> - Bert -
>
>
>


--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Bert Freudenberg-3
Given your application field, SoundBuffer should be fine.

- Bert -

Am 19.07.2006 um 13:40 schrieb Eugene Beschastnov:

> I'm not very good in C, but as I understand - yes, it is typedef for
> 'short*', but it's standard typedef.
>
> Anyway, what kind of data should I use to call FFI function that
> expects 'short*'?
>
> To be more specific, C function is
> __declspec(dllexport) BE_ERR    beEncodeChunk(HBE_STREAM hbeStream,
> DWORD nSamples, PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput);
> ========================================================
> For this function I made this apicall construction:
> apiBeEncodeChunkHbeStream: hbeStream nSamples: nSamples pSamples:
> pSamples pOutput: pOutput pdwOutput: pdwOutput
>    <apicall: ulong 'beEncodeChunk' ( ulong long short* byte* long* )
> module: 'lame_enc.dll'>
>    ^self externalCallFailed
> ========================================================
> And I'm trying to call it in following way:
> pMp3Buffer := ByteArray new: dwMp3Buffer.
> samples := (SampledSound fromWaveFileNamed: 'Message.wav')  
> asSampledSound
> samples asWordArray.
> startOfChunk := 1.
> mp3Output := ByteArray new: 0.
> [startOfChunk <= samples size] whileTrue:
> [endOfChunk := startOfChunk + dwSamples - 1 min: samples size.
> buf := samples copyFrom: startOfChunk to: endOfChunk.
> startOfChunk := endOfChunk + 1.
> pDwWrite := WordArray new: 1.
> errCode := self
> apiBeEncodeChunkHbeStream: hbeStream
> nSamples: buf size
> pSamples: buf
> pOutput: pMp3Buffer
> pdwOutput: pDwWrite.
> errCode ~= self beErrSuccessful
> ifTrue:
> [self apiBeCloseStreamHbeStream: hbeStream.
> Exception signal: 'beEncodeChunk() failed (' , errCode  
> asString , ')'].
> mp3Output addAll: (pMp3Buffer copyFrom: 1 to: pDwWrite first)].
> (FileStream fileNamed: 'Message.mp3') binary
> next: mp3Output size
> putAll: mp3Output
> startingAt: 1
>
> hbeStream, dwSamples and dwMp3Buffer are got from FFI function
> 'beInitStream', which is called earlier and executed correctly.
>
> 2006/7/19, Bert Freudenberg <[hidden email]>:
>> Am 19.07.2006 um 12:33 schrieb Eugene Beschastnov:
>>
>> > Another question - what construction in Squeak corresponds to
>> > PSHORT in C?
>>
>> There is no type PSHORT in C. It probably is a typedef (could be a
>> macro too) which you need to lookup in the headers.
>>
>> I'd guess it's a 'short*'.
>>
>> - Bert -
>>
>>
>>
>
>
> --
> Eugene




Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
So
        samples := (SampledSound fromWaveFileNamed: 'Message.wav')
asSampledSound samples.
        'some code skipped...'
        buf := samples copyFrom: startOfChunk to: endOfChunk.
        'some more code skipped...'
        errCode := self
                        apiBeEncodeChunkHbeStream: hbeStream
                        nSamples: buf size
                        pSamples: buf
                        pOutput: pMp3Buffer
                        pdwOutput: pDwWrite.

should be OK? But I already tried this and VM crashed (just checked again).

Here is stack dump, but I don't see any helpful in it:
---------------------------------------------------------------------
Wed Jul 19 21:48:10 2006

Exception code: C0000005
Exception addr: 04AD26D8
Access violation (write access) at 11A0A000
EAX:00000000    EBX:04BA0048    ECX:00000010    EDX:000000D8
ESI:04B91B98    EDI:11A0A000    EBP:04BA7D6C    ESP:000670B8
EIP:04AD26D8    EFL:00010206
FP Control: FFFF027F
FP Status:  FFFF4877
FP Tag:     FFFFFFFF
VM Version: Squeak 3.7.1 (release) from Sep 23 2004
Compiler: gcc 2.95.2 19991024 (release)

Current byte code: 32
Primitive index: 120

Loaded plugins:
    SocketPlugin 23 September 2004 (i)
    lame_enc.dll
    SqueakFFIPrims 23 September 2004 (e)
    SoundPlugin 23 September 2004 (i)
    LargeIntegers v1.3 23 September 2004 (i)
    Matrix2x3Plugin 23 September 2004 (i)
    FloatArrayPlugin 23 September 2004 (i)
    B2DPlugin 23 September 2004 (i)
    BitBltPlugin 23 September 2004 (i)
    SecurityPlugin 23 September 2004 (i)
    FilePlugin 23 September 2004 (i)
    MiscPrimitivePlugin 23 September 2004 (i)


Stack dump:

291203288 LameEncoder class>testEncode
291203176 UndefinedObject>DoIt
291200616 Compiler>evaluate:in:to:notifying:ifFail:logged:
291200708 [] in ParagraphEditor>evaluateSelection
291200432 BlockContext>on:do:
291200340 ParagraphEditor>evaluateSelection
291200248 ParagraphEditor>doIt
291200524 [] in ParagraphEditor>doIt:
291200156 Controller>terminateAndInitializeAround:
291200064 ParagraphEditor>doIt:
291199816 ParagraphEditor>dispatchOnCharacter:with:
291199724 TextMorphEditor>dispatchOnCharacter:with:
291199632 ParagraphEditor>readKeyboard
291199540 TextMorphEditor>readKeyboard
291199176 [] in TextMorph>keyStroke:
291199084 TextMorph>handleInteraction:fromEvent:
291198992 TextMorphForEditView>handleInteraction:fromEvent:
291198848 TextMorph>keyStroke:
291198756 TextMorphForEditView>keyStroke:
291198664 TextMorph>handleKeystroke:
291198296 KeyboardEvent>sentTo:
291198204 Morph>handleEvent:
291198112 Morph>handleFocusEvent:
291198388 [] in HandMorph>sendFocusEvent:to:clear:
291198480 [] in PasteUpMorph>becomeActiveDuring:
291198020 BlockContext>on:do:
291197928 PasteUpMorph>becomeActiveDuring:
291197704 HandMorph>sendFocusEvent:to:clear:
291197612 HandMorph>sendEvent:focus:clear:
291197520 HandMorph>sendKeyboardEvent:
291197428 HandMorph>handleEvent:
291197208 HandMorph>processEvents
291197300 [] in WorldState>doOneCycleNowFor:
291197116 SequenceableCollection>do:
291197024 WorldState>handsDo:
291196932 WorldState>doOneCycleNowFor:
291196840 WorldState>doOneCycleFor:
291196748 PasteUpMorph>doOneCycle
288143892 [] in Project class>spawnNewProcess
288144076 [] in BlockContext>newProcess



2006/7/19, Bert Freudenberg <[hidden email]>:
> Given your application field, SoundBuffer should be fine.
>
> - Bert -

--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Bert Freudenberg-3
I think it looks fine. But there's a lot that can go wrong when you  
do FFI. You need to check and double-check everything actually does  
what you think it does. A C debugger might help, too.

- Bert -

Am 19.07.2006 um 17:06 schrieb Eugene Beschastnov:

> So
> samples := (SampledSound fromWaveFileNamed: 'Message.wav')
> asSampledSound samples.
> 'some code skipped...'
> buf := samples copyFrom: startOfChunk to: endOfChunk.
> 'some more code skipped...'
> errCode := self
> apiBeEncodeChunkHbeStream: hbeStream
> nSamples: buf size
> pSamples: buf
> pOutput: pMp3Buffer
> pdwOutput: pDwWrite.
>
> should be OK? But I already tried this and VM crashed (just checked  
> again).
>
> Here is stack dump, but I don't see any helpful in it:
> ---------------------------------------------------------------------
> Wed Jul 19 21:48:10 2006
>
> Exception code: C0000005
> Exception addr: 04AD26D8
> Access violation (write access) at 11A0A000
> EAX:00000000    EBX:04BA0048    ECX:00000010    EDX:000000D8
> ESI:04B91B98    EDI:11A0A000    EBP:04BA7D6C    ESP:000670B8
> EIP:04AD26D8    EFL:00010206
> FP Control: FFFF027F
> FP Status:  FFFF4877
> FP Tag:     FFFFFFFF
> VM Version: Squeak 3.7.1 (release) from Sep 23 2004
> Compiler: gcc 2.95.2 19991024 (release)
>
> Current byte code: 32
> Primitive index: 120
>
> Loaded plugins:
>    SocketPlugin 23 September 2004 (i)
>    lame_enc.dll
>    SqueakFFIPrims 23 September 2004 (e)
>    SoundPlugin 23 September 2004 (i)
>    LargeIntegers v1.3 23 September 2004 (i)
>    Matrix2x3Plugin 23 September 2004 (i)
>    FloatArrayPlugin 23 September 2004 (i)
>    B2DPlugin 23 September 2004 (i)
>    BitBltPlugin 23 September 2004 (i)
>    SecurityPlugin 23 September 2004 (i)
>    FilePlugin 23 September 2004 (i)
>    MiscPrimitivePlugin 23 September 2004 (i)
>
>
> Stack dump:
>
> 291203288 LameEncoder class>testEncode
> 291203176 UndefinedObject>DoIt
> 291200616 Compiler>evaluate:in:to:notifying:ifFail:logged:
> 291200708 [] in ParagraphEditor>evaluateSelection
> 291200432 BlockContext>on:do:
> 291200340 ParagraphEditor>evaluateSelection
> 291200248 ParagraphEditor>doIt
> 291200524 [] in ParagraphEditor>doIt:
> 291200156 Controller>terminateAndInitializeAround:
> 291200064 ParagraphEditor>doIt:
> 291199816 ParagraphEditor>dispatchOnCharacter:with:
> 291199724 TextMorphEditor>dispatchOnCharacter:with:
> 291199632 ParagraphEditor>readKeyboard
> 291199540 TextMorphEditor>readKeyboard
> 291199176 [] in TextMorph>keyStroke:
> 291199084 TextMorph>handleInteraction:fromEvent:
> 291198992 TextMorphForEditView>handleInteraction:fromEvent:
> 291198848 TextMorph>keyStroke:
> 291198756 TextMorphForEditView>keyStroke:
> 291198664 TextMorph>handleKeystroke:
> 291198296 KeyboardEvent>sentTo:
> 291198204 Morph>handleEvent:
> 291198112 Morph>handleFocusEvent:
> 291198388 [] in HandMorph>sendFocusEvent:to:clear:
> 291198480 [] in PasteUpMorph>becomeActiveDuring:
> 291198020 BlockContext>on:do:
> 291197928 PasteUpMorph>becomeActiveDuring:
> 291197704 HandMorph>sendFocusEvent:to:clear:
> 291197612 HandMorph>sendEvent:focus:clear:
> 291197520 HandMorph>sendKeyboardEvent:
> 291197428 HandMorph>handleEvent:
> 291197208 HandMorph>processEvents
> 291197300 [] in WorldState>doOneCycleNowFor:
> 291197116 SequenceableCollection>do:
> 291197024 WorldState>handsDo:
> 291196932 WorldState>doOneCycleNowFor:
> 291196840 WorldState>doOneCycleFor:
> 291196748 PasteUpMorph>doOneCycle
> 288143892 [] in Project class>spawnNewProcess
> 288144076 [] in BlockContext>newProcess


Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

johnmci
In reply to this post by Eugene Beschastnov
So how many bytes are being allocated here?
how many bytes do you expect to write into that location?
Are these bytes, or words you're expecting?   1 word -> 4 bytes?

On 19-Jul-06, at 4:40 AM, Eugene Beschastnov wrote:

> And I'm trying to call it in following way:
> pMp3Buffer := ByteArray new: dwMp3Buffer.


Lastly I'll note that

mp3Output addAll: (pMp3Buffer copyFrom: 1 to: pDwWrite first)].

could be expressed as this, since the copyFrom:to: makes a new object  
of the same class as the original,
no need to stuff that new object into  mp3Output.

mp3Output := pMp3Buffer copyFrom: 1 to: pDwWrite first.

regarding

pDwWrite first

Ah, likely you should do
pDwWrite := ByteArray new: 4.

then say pDwWrite signedLongAt: 1
if it's  a signed long in platform endian you expect to find there,  
this is clearer than hoping the
value you got stuff in there is an integer of some sort in the right  
endian format.


--
========================================================================
===
John M. McIntosh <[hidden email]>
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
========================================================================
===



Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
In reply to this post by Bert Freudenberg-3
I digged a little into C-code and found that hbeStream is pointer to
some LAME data (some global flags are stored there). I suppose that
root of problem is that this data is destroyed or moved between
apicalls. Is there any way to avoid this?

--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Eugene Beschastnov
Is it possible that Squeak closes external library (in my case it is
DLL) after every external function call? If yes, is it possible to
force it to not close external library (I'd prefer to close it
manually when needed, but even staying it opened is good enough).

--
Eugene

Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Andreas.Raab
Eugene Beschastnov wrote:
> Is it possible that Squeak closes external library (in my case it is
> DLL) after every external function call?

No.

Cheers,
   - Andreas


Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Nicolas Cellier-3
In reply to this post by Eugene Beschastnov

I retry sending since it failed...

----------  Message transmis  ----------
Subject: Re: Help with FFI - another try
Date: Vendredi 21 Juillet 2006 22:49
From: nicolas cellier <[hidden email]>
To: The general-purpose Squeak developers list
<[hidden email]>

Le Vendredi 21 Juillet 2006 13:15, Eugene Beschastnov a écrit :
> I digged a little into C-code and found that hbeStream is pointer to
> some LAME data (some global flags are stored there). I suppose that
> root of problem is that this data is destroyed or moved between
> apicalls. Is there any way to avoid this?

One solution is to allocate this data on external heap.
(See ExternalAddress class>>allocate:) instead of using a ByteArray in
Smalltalk memory.

Of course, you'll have to free data yourself as in C.
Maybe the trick explained at http://bugs.impara.de/view.php?id=3692 that
should be in latest image can help...

Nicolas

-------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Nicolas Cellier-3
In reply to this post by Eugene Beschastnov
I retry sending because it failed...

----------  Message transmis  ----------
Subject: Re: Help with FFI - another try
Date: Vendredi 21 Juillet 2006 23:13
From: nicolas cellier <[hidden email]>
To: Squeak-dev developers list general-purpose Squeak
<[hidden email]>

Le Vendredi 21 Juillet 2006 22:49, nicolas cellier a écrit :

> Le Vendredi 21 Juillet 2006 13:15, Eugene Beschastnov a écrit :
> > I digged a little into C-code and found that hbeStream is pointer to
> > some LAME data (some global flags are stored there). I suppose that
> > root of problem is that this data is destroyed or moved between
> > apicalls. Is there any way to avoid this?
>
> One solution is to allocate this data on external heap.
> (See ExternalAddress class>>allocate:) instead of using a ByteArray in
> Smalltalk memory.
>
> Of course, you'll have to free data yourself as in C.
> Maybe the trick explained at http://bugs.impara.de/view.php?id=3692 that
> should be in latest image can help...
>
> Nicolas

My last post was too short: i remember it is not that obvious to guess the
right object which should be passed as FFI call argument.

It is an ExternalData, a combination of an ExternalAddress and an
ExternalType.

And one more thing: don't expect ExternalAddress to survive across image
snapshots. If you want to survive, you must transfer data into a ByteArray
before saving the image, and transfer to a newly allocated ExternalAddress
before next use... But maybe this is not a problem.

in Smallapack-Collection, i have a class ExternalArray doing this kind of
tirck:

ExternalArray>>resetExternalData
 "Reset the ExternalData object used as FFI argument.
 This is cached in an inst-var instead of being recreated at each call.
 However, this must be reset whenever handle is changed"

 | cType |

 cType := self class type.
 data := cType isStructureType
  ifTrue: [
   "Arrays of structure cannot carry type checking in FFI"
   ExternalData fromHandle: handle type: ExternalType void]
  ifFalse: [
   "Atomic types"
   ExternalData fromHandle: handle type: cType]

where handle is sometimes a ByteArray in Smalltalk memory, sometimes an
ExternalAddress according to my needs.

ExternalArray>>copyInCSpace
 "Answer a copy of self with data in C space"

 ^self shallowCopy postCopyInCSpace

ExternalArray>>postCopyInCSpace
 "Copy the data into a new array"

 | newHandle bs |

 handle isNil
  ifFalse: [bs := self byteSize.
   newHandle := ExternalAddress gcallocate: bs.
   self
    memcpyDest: newHandle
    fromSource: handle
    nBytes: bs.
   self setHandle: newHandle]

Maybe you have enough elements or you can browse more at squeak source
http://www.squeaksource.com/@ZGaVjYGiHOshVjSM/LGmmIzpi

Nicolas

-------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: Help with FFI - another try

Nicolas Cellier-3
In reply to this post by Andreas.Raab
Le Lundi 24 Juillet 2006 13:37, Andreas Raab a écrit :
> Eugene Beschastnov wrote:
> > Is it possible that Squeak closes external library (in my case it is
> > DLL) after every external function call?
>
> No.
>
> Cheers,
>    - Andreas

If really wanted, you would have to hack the plugin...
Is there any use of unloading a DLL?

Nicolas