Passing an array of structures to an external function

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

Passing an array of structures to an external function

Esteban A. Maringolo-2
Hi,

        I'm trying yo use an external call to an API.
        I don't know if it isn't working because something else, or, as the
subject mentions, because I don't know how to pass an array of
structures to the function

        The function is:

BOOL GradientFill(
   HDC hdc,                   // handle to DC
   PTRIVERTEX pVertex,        // array of vertices
   ULONG dwNumVertex,         // number of vertices
   PVOID pMesh,               // array of gradients
   ULONG dwNumMesh,           // size of gradient array
   ULONG dwMode               // gradient fill mode
);

        And I'm implementing the call this way:

        <stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>

        The argument pVertex is
        StructureArray length: 2 elementClass: TRIVERTEX.

        Perhaps a reference of how to MAP structs and argument types from
Win32 to Dolphin will be useful.

        Best regards,


--
Esteban A. Maringolo
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Esteban A. Maringolo-2
Esteban A. Maringolo escribió:
>     And I'm implementing the call this way:
>
>     <stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>
>
>     The argument pVertex is
>     StructureArray length: 2 elementClass: TRIVERTEX.


I've solved it.
The call was being sent correctly.
I was missing other thing :-)

<stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>


When available, i'll publish a small goodie in
http://www.smalltalking.net/Goodies/Dolphin/

Best regards.

--
Esteban A. Maringolo
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Schwab,Wilhelm K
In reply to this post by Esteban A. Maringolo-2
Esteban,

> Hi,
>
>     I'm trying yo use an external call to an API.
>     I don't know if it isn't working because something else, or, as the
> subject mentions, because I don't know how to pass an array of
> structures to the function
>
>     The function is:
>
> BOOL GradientFill(
>   HDC hdc,                   // handle to DC
>   PTRIVERTEX pVertex,        // array of vertices
>   ULONG dwNumVertex,         // number of vertices
>   PVOID pMesh,               // array of gradients
>   ULONG dwNumMesh,           // size of gradient array
>   ULONG dwMode               // gradient fill mode
> );
>
>     And I'm implementing the call this way:
>
>     <stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>
>
>     The argument pVertex is
>     StructureArray length: 2 elementClass: TRIVERTEX.
>
>     Perhaps a reference of how to MAP structs and argument types from
> Win32 to Dolphin will be useful.

Search Ian's archives, and read the Education Centre; there is plenty of
information on how Dolphin approaches it.  Warning: much of it is terse,
but you appear to be more than ready to start reading it.  There is a
help file for the Win32 API, and there is also a type library that you
can use.  The bad news on the latter is that it is VB specific, which
means it uses some strange types to compensate for deficiencies of VB.
The archives will contain file names and URLs.

With all of that said, I think you can simply declare your pVertex
parameter as TRIVERTEX*.  The more recent Dolphin compilers are much
more savy about types than the early compilers.  The other thing, which
goes back to Dolphin's early days, is that Dolphin will automatically
pass many external structures, byte array, etc. by address.  If you read
the archives carefully, you will catch a hint of regret here and there,
but it most likely avoids far more trouble that causes.  It becomes a
problem when you are given an address and want to pass it to a function;
the remedy is to wrap it in something whose address will be taken, or
something like that.

Huh?  Fair enough.  Declare the parameter as TRIVERTEX* and simply pass
the array; do _not_ bother to take its address.  Also, be sure to give
the correct value for dwNumVertex - any integer (it will be a
SmallInteger if you look carefully) will suffice.

Please make a backup of your image before messing around with this
stuff; then have fun with it.  There is some good info on backups on the
Wiki.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Udo Schneider
In reply to this post by Esteban A. Maringolo-2
Hi Esteban,

this might save you some time.

CU,

Udo


Esteban A. Maringolo wrote:

> Hi,
>
>     I'm trying yo use an external call to an API.
>     I don't know if it isn't working because something else, or, as the
> subject mentions, because I don't know how to pass an array of
> structures to the function
>
>     The function is:
>
> BOOL GradientFill(
>   HDC hdc,                   // handle to DC
>   PTRIVERTEX pVertex,        // array of vertices
>   ULONG dwNumVertex,         // number of vertices
>   PVOID pMesh,               // array of gradients
>   ULONG dwNumMesh,           // size of gradient array
>   ULONG dwMode               // gradient fill mode
> );
>
>     And I'm implementing the call this way:
>
>     <stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>
>
>     The argument pVertex is
>     StructureArray length: 2 elementClass: TRIVERTEX.
>
>     Perhaps a reference of how to MAP structs and argument types from
> Win32 to Dolphin will be useful.
>
>     Best regards,
>
>

| package |
package := Package name: 'US GradientFill'.
package paxVersion: 0;
        basicComment: 'dib := DIBSection
                        width: 160
                        height: 120
                        depth: 32.
vertexs := StructureArray length: 5 elementClass: TRIVERTEX.
vertexs
        at: 1 put: (TRIVERTEX position: 0 @ 0 color: Color red);
        at: 2 put: (TRIVERTEX position: dib extent x @ 0 color: Color yellow);
        at: 3 put: (TRIVERTEX position: dib extent x @ dib extent y color: Color green);
        at: 4 put: (TRIVERTEX position: 0 @ dib extent y color: Color blue);
        at: 5
                put: (TRIVERTEX position: (dib extent x / 2 ) @ (dib extent y / 2) color: Color cyan).
meshes := StructureArray length: 4 elementClass: GRADIENT_TRIANGLE.
meshes
        at: 1
                put: (mesh := GRADIENT_TRIANGLE
                                                vertex1: 0
                                                vertex2: 1
                                                vertex3: 4);
        at: 2
                put: (mesh := GRADIENT_TRIANGLE
                                                vertex1: 1
                                                vertex2: 2
                                                vertex3: 4);
        at: 3
                put: (mesh := GRADIENT_TRIANGLE
                                                vertex1: 2
                                                vertex2: 3
                                                vertex3: 4);
        at: 4
                put: (mesh := GRADIENT_TRIANGLE
                                                vertex1: 3
                                                vertex2: 0
                                                vertex3: 4).
canvas := dib canvas.
"canvas := MetafileCanvas onFile: ''s:\test.emf''."
return := Msimg32Library default
                        gradientFill: canvas asParameter
                        pVertex: vertexs
                        dwNumVertex: vertexs size
                        pMesh: meshes
                        dwNumMesh: meshes size
                        dwMode: 2.
canvas := nil.
ImagePresenter showOn: dib


"
//
// gradient drawing modes
//

#define GRADIENT_FILL_RECT_H    0x00000000
#define GRADIENT_FILL_RECT_V    0x00000001
#define GRADIENT_FILL_TRIANGLE  0x00000002
#define GRADIENT_FILL_OP_FLAG   0x000000ff
"
'.

package basicPackageVersion: '0.003'.

package basicScriptAt: #preinstall put: 'Win32Constants at: #GRADIENT_FILL_RECT_H put: 0;
at: #GRADIENT_FILL_RECT_V put: 1;
at: #GRADIENT_FILL_TRIANGLE put: 2;
at: #GRADIENT_FILL_OP_FLAG put: 16rFF.
'.

package classNames
        add: #GRADIENT_RECT;
        add: #GRADIENT_TRIANGLE;
        add: #TRIVERTEX;
        yourself.

package methodNames
        add: #Canvas -> #gradientFillVertex:meshes:mode:;
        add: #Canvas -> #gradientRectangle:from:to:mode:;
        add: #Canvas -> #horizontalGradientRectangle:from:to:;
        add: #Canvas -> #verticalGradientRectangle:from:to:;
        add: #Msimg32Library -> #gradientFill:pVertex:dwNumVertex:pMesh:dwNumMesh:dwMode:;
        yourself.

package binaryGlobalNames: (Set new
        yourself).

package globalAliases: (Set new
        yourself).

package allResourceNames: (Set new
        yourself).

package setPrerequisites: (IdentitySet new
        add: '..\Object Arts\Dolphin\Base\Dolphin';
        add: '..\Object Arts\Dolphin\MVP\Base\Dolphin MVP Base';
        yourself).

package!

"Class Definitions"!

ExternalStructure subclass: #GRADIENT_RECT
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        classInstanceVariableNames: ''!
ExternalStructure subclass: #GRADIENT_TRIANGLE
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        classInstanceVariableNames: ''!
ExternalStructure subclass: #TRIVERTEX
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        classInstanceVariableNames: ''!

"Global Aliases"!


"Loose Methods"!

!Canvas methodsFor!

gradientFillVertex: vertexs meshes: meshes mode: dwMode
        ^Msimg32Library default
                gradientFill: self asParameter
                pVertex: vertexs
                dwNumVertex: vertexs size
                pMesh: meshes
                dwNumMesh: meshes size
                dwMode: dwMode!

gradientRectangle: aRectangle from: fromColor to: toColor mode: dwMode
        | vertexs meshes |
        vertexs := StructureArray length: 2 elementClass: TRIVERTEX.
        vertexs
                at: 1 put: (TRIVERTEX position: aRectangle topLeft color: fromColor);
                at: 2 put: (TRIVERTEX position: aRectangle bottomRight color: toColor).
        meshes := StructureArray length: 1 elementClass: GRADIENT_RECT.
        meshes at: 1 put: (GRADIENT_RECT upperLeft: 0 lowerRight: 1).
        self
                gradientFillVertex: vertexs
                meshes: meshes
                mode: dwMode!

horizontalGradientRectangle: aRectangle from: fromColor to: toColor
self gradientRectangle: aRectangle from:fromColor to:toColor mode: GRADIENT_FILL_RECT_H
!

verticalGradientRectangle: aRectangle from: fromColor to: toColor
        self
                gradientRectangle: aRectangle
                from: fromColor
                to: toColor
                mode: GRADIENT_FILL_RECT_V! !
!Canvas categoriesFor: #gradientFillVertex:meshes:mode:!drawing!private! !
!Canvas categoriesFor: #gradientRectangle:from:to:mode:!drawing!private! !
!Canvas categoriesFor: #horizontalGradientRectangle:from:to:!drawing!public! !
!Canvas categoriesFor: #verticalGradientRectangle:from:to:!drawing!public! !

!Msimg32Library methodsFor!

gradientFill: hdc pVertex: pVertex dwNumVertex: dwNumVertex pMesh: pMesh dwNumMesh: dwNumMesh dwMode: dwMode
        "Fills rectangle and triangle structures

        BOOL GradientFill(
                HDC hdc,                   // handle to DC
                PTRIVERTEX pVertex,        // array of vertices
                ULONG dwNumVertex,         // number of vertices
                PVOID pMesh,               // array of gradients
                ULONG dwNumMesh,           // size of gradient array
                ULONG dwMode               // gradient fill mode
        ); "

        <stdcall: bool GradientFill handle lpvoid dword lpvoid dword dword>
        ^self invalidCall! !
!Msimg32Library categoriesFor: #gradientFill:pVertex:dwNumVertex:pMesh:dwNumMesh:dwMode:!public! !

"End of package definition"!

"Source Globals"!

"Classes"!

GRADIENT_RECT guid: (GUID fromString: '{7ADEF804-3D6B-44ED-B937-1F9AB062CE46}')!
GRADIENT_RECT comment: ''!
!GRADIENT_RECT categoriesForClass!Unclassified! !
!GRADIENT_RECT methodsFor!

lowerRight
        "Answer the receiver's lowerRight field as a Smalltalk object."

        ^(bytes dwordAtOffset: 4)!

lowerRight: anObject
        "Set the receiver's lowerRight field to the value of anObject."

        bytes dwordAtOffset: 4 put: anObject!

upperLeft
        "Answer the receiver's upperLeft field as a Smalltalk object."

        ^(bytes dwordAtOffset: 0)!

upperLeft: anObject
        "Set the receiver's upperLeft field to the value of anObject."

        bytes dwordAtOffset: 0 put: anObject! !
!GRADIENT_RECT categoriesFor: #lowerRight!**compiled accessors**!public! !
!GRADIENT_RECT categoriesFor: #lowerRight:!**compiled accessors**!public! !
!GRADIENT_RECT categoriesFor: #upperLeft!**compiled accessors**!public! !
!GRADIENT_RECT categoriesFor: #upperLeft:!**compiled accessors**!public! !

!GRADIENT_RECT class methodsFor!

defineFields
        "Define the fields of the Win32 GRADIENT_RECT structure
                self compileDefinition

        typedef struct _GRADIENT_RECT {
                ULONG    UpperLeft;
                ULONG    LowerRight;
        }GRADIENT_RECT;"

        self
                defineField: #upperLeft type: DWORDField new;
                defineField: #lowerRight type: DWORDField new!

upperLeft: upperLeft lowerRight: lowerRight
^self new upperLeft: upperLeft; lowerRight: lowerRight; yourself! !
!GRADIENT_RECT class categoriesFor: #defineFields!initializing!public! !
!GRADIENT_RECT class categoriesFor: #upperLeft:lowerRight:!public! !

GRADIENT_TRIANGLE guid: (GUID fromString: '{C65A9E2C-8E5E-4BE4-924A-04A9E33EEFD3}')!
GRADIENT_TRIANGLE comment: ''!
!GRADIENT_TRIANGLE categoriesForClass!Unclassified! !
!GRADIENT_TRIANGLE methodsFor!

vertex1
        "Answer the receiver's vertex1 field as a Smalltalk object."

        ^(bytes dwordAtOffset: 0)!

vertex1: anObject
        "Set the receiver's vertex1 field to the value of anObject."

        bytes dwordAtOffset: 0 put: anObject!

vertex2
        "Answer the receiver's vertex2 field as a Smalltalk object."

        ^(bytes dwordAtOffset: 4)!

vertex2: anObject
        "Set the receiver's vertex2 field to the value of anObject."

        bytes dwordAtOffset: 4 put: anObject!

vertex3
        "Answer the receiver's vertex3 field as a Smalltalk object."

        ^(bytes dwordAtOffset: 8)!

vertex3: anObject
        "Set the receiver's vertex3 field to the value of anObject."

        bytes dwordAtOffset: 8 put: anObject! !
!GRADIENT_TRIANGLE categoriesFor: #vertex1!**compiled accessors**!public! !
!GRADIENT_TRIANGLE categoriesFor: #vertex1:!**compiled accessors**!public! !
!GRADIENT_TRIANGLE categoriesFor: #vertex2!**compiled accessors**!public! !
!GRADIENT_TRIANGLE categoriesFor: #vertex2:!**compiled accessors**!public! !
!GRADIENT_TRIANGLE categoriesFor: #vertex3!**compiled accessors**!public! !
!GRADIENT_TRIANGLE categoriesFor: #vertex3:!**compiled accessors**!public! !

!GRADIENT_TRIANGLE class methodsFor!

defineFields
        "Define the fields of the Win32 GRADIENT_TRIANGLE structure
                self compileDefinition

        typedef struct _GRADIENT_TRIANGLE {
                ULONG    Vertex1;
                ULONG    Vertex2;
                ULONG    Vertex3;
        }GRADIENT_TRIANGLE;"

        self
                defineField: #vertex1 type: DWORDField new;
                defineField: #vertex2 type: DWORDField new;
        defineField: #vertex3 type: DWORDField new!

vertex1: vertex1 vertex2: vertex2 vertex3: vertex3
        ^(self new)
                vertex1: vertex1;
                vertex2: vertex2;
                vertex3: vertex3;
                yourself! !
!GRADIENT_TRIANGLE class categoriesFor: #defineFields!initializing!public! !
!GRADIENT_TRIANGLE class categoriesFor: #vertex1:vertex2:vertex3:!public! !

TRIVERTEX guid: (GUID fromString: '{32066DEF-7DC0-4D81-989E-90D38D2A6AF4}')!
TRIVERTEX comment: ''!
!TRIVERTEX categoriesForClass!Unclassified! !
!TRIVERTEX methodsFor!

alpha
        "Answer the receiver's alpha field as a Smalltalk object."

        ^(bytes wordAtOffset: 14)!

alpha: anObject
        "Set the receiver's alpha field to the value of anObject."

        bytes wordAtOffset: 14 put: anObject!

blue
        "Answer the receiver's blue field as a Smalltalk object."

        ^(bytes wordAtOffset: 12)!

blue: anObject
        "Set the receiver's blue field to the value of anObject."

        bytes wordAtOffset: 12 put: anObject!

color: aColor
        self
                red: aColor asRGB red * 16rFF;
                green: aColor asRGB green * 16rFF;
                blue: aColor asRGB blue * 16rFF!

green
        "Answer the receiver's green field as a Smalltalk object."

        ^(bytes wordAtOffset: 10)!

green: anObject
        "Set the receiver's green field to the value of anObject."

        bytes wordAtOffset: 10 put: anObject!

position
        ^self x@self y!

position: aPoint
        self x: aPoint x; y: aPoint y!

red
        "Answer the receiver's red field as a Smalltalk object."

        ^(bytes wordAtOffset: 8)!

red: anObject
        "Set the receiver's red field to the value of anObject."

        bytes wordAtOffset: 8 put: anObject!

x
        "Answer the receiver's x field as a Smalltalk object."

        ^(bytes sdwordAtOffset: 0)!

x: anObject
        "Set the receiver's x field to the value of anObject."

        bytes sdwordAtOffset: 0 put: anObject!

y
        "Answer the receiver's y field as a Smalltalk object."

        ^(bytes sdwordAtOffset: 4)!

y: anObject
        "Set the receiver's y field to the value of anObject."

        bytes sdwordAtOffset: 4 put: anObject! !
!TRIVERTEX categoriesFor: #alpha!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #alpha:!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #blue!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #blue:!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #color:!public! !
!TRIVERTEX categoriesFor: #green!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #green:!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #position!public! !
!TRIVERTEX categoriesFor: #position:!public! !
!TRIVERTEX categoriesFor: #red!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #red:!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #x!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #x:!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #y!**compiled accessors**!public! !
!TRIVERTEX categoriesFor: #y:!**compiled accessors**!public! !

!TRIVERTEX class methodsFor!

defineFields
        "Define the fields of the Win32 TRIVERTEX  structure
                self compileDefinition

        typedef struct _TRIVERTEX {
                LONG        x;
                LONG        y;
                COLOR16     Red;
                COLOR16     Green;
                COLOR16     Blue;
                COLOR16     Alpha;
        }TRIVERTEX; "

        self
                defineField: #x type: SDWORDField new;
                defineField: #y type: SDWORDField new;
                defineField: #red type: WORDField new;
                defineField: #green type: WORDField new;
                defineField: #blue type: WORDField new;
                defineField: #alpha type: WORDField new!

position: aPoint color: aColor
        ^self new position: aPoint; color: aColor; yourself.! !
!TRIVERTEX class categoriesFor: #defineFields!initializing!public! !
!TRIVERTEX class categoriesFor: #position:color:!public! !

"Binary Globals"!

"Resources"!

Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Esteban A. Maringolo-2
Udo Schneider escribió:
> Hi Esteban,
> this might save you some time.

Thanks Udo, but i've solved it before you sent me the package :-)

The only constant I didn't use was:
 > #define GRADIENT_FILL_OP_FLAG   0x000000ff
You can tell me what is it's purpose, if you want.


I'm happy with my implementation, so I won't change it (because its
mine :-) )

Anyway, things like this make me feel Dolphin needs an STORE like
repository. Owned by Object-Arts (the repository, not it's contents).

Best regards.

--
Esteban A. Maringolo
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Udo Schneider
Esteban A. Maringolo wrote:
> Thanks Udo, but i've solved it before you sent me the package :-)
Never mind - next time I'm may be quicker ;-)

> The only constant I didn't use was:
>  > #define GRADIENT_FILL_OP_FLAG   0x000000ff
> You can tell me what is it's purpose, if you want.
To be honest ..... no idea. This one slipped in while converting the .h
defines for Gradient Fills.

I didn't find anything in MSDN neither ... so maybe this is a constant
for something implemented but not documented ... wouldn't be the first
time ... especially for M$ :-(


> I'm happy with my implementation, so I won't change it (because its mine
> :-) )
I know these feelings ..... :-)

> Anyway, things like this make me feel Dolphin needs an STORE like
> repository. Owned by Object-Arts (the repository, not it's contents).
I'm currently implementing something like this. I'll call it
"DolphinMap" (which is heavily inspired by SqueakMap). There was a
discussion regarding this topic:
http://groups.google.de/groups?q=dolphinmap&hl=de&lr=&client=firefox-a&rls=org.mozilla:en-US:official&selm=41b71db0%40news.totallyobjects.com&rnum=1

Any comments/suggestions are highly appreciated.

CU,

Udo


>
> Best regards.
>


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

David Gorisek-5
Udo Schneider wrote:

> Esteban A. Maringolo wrote:
>
>> Anyway, things like this make me feel Dolphin needs an STORE like
>> repository. Owned by Object-Arts (the repository, not it's contents).
>
> I'm currently implementing something like this. I'll call it
> "DolphinMap" (which is heavily inspired by SqueakMap). There was a
> discussion regarding this topic:
> http://groups.google.de/groups?q=dolphinmap&hl=de&lr=&client=firefox-a&rls=org.mozilla:en-US:official&selm=41b71db0%40news.totallyobjects.com&rnum=1 
>

Hm, I wish I had some free time to do this. We already have all that is
  needed here: OmniBase + STS + web server frameworks. We could make
this work in a week.

If I were you or if I had the time and budget to do it, I would make a
web front end to STS repository which would allow browsing of code in
the repository. This would work like the Mozilla source code repository
over the web. Then one could select a package version or any other piece
of code, download and install it locally. Also for better integration
with Dolphin, I would add a possibility to browse remote repositories
using the usual STS source code browsers.

Best regards,

David


Reply | Threaded
Open this post in threaded view
|

Re: Passing an array of structures to an external function

Udo Schneider
David,


> If I were you or if I had the time and budget to do it, I would make a
> web front end to STS repository which would allow browsing of code in
> the repository. This would work like the Mozilla source code repository
> over the web. Then one could select a package version or any other piece
> of code, download and install it locally. Also for better integration
> with Dolphin, I would add a possibility to browse remote repositories
> using the usual STS source code browsers.
This would be the ultimate goal. I started a little bit simpler with the
idea of a central package "directory" which lists all the known packages
  - so more some kind of 1to1 port of SqueakMap.

As said above the ultimate tool would be something like STS with a web
Frontend ... I'm only curious about licensing: As only one "image" would
connect to STS/OmniBase a single user license would be sufficient ....
although multiple web sessions are handled by this image. So I think one
should think about a general licensing scheme in this case.

Regards,

Udo