Newsgroups: comp.lang.smalltalk
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news4.ner.bbnplanet.net!news.ner.bbnplanet.net!howland.reston.ans.net!cs.utexas.edu!news.ti.com!ticipa!clw
From: clw@ticipa.works.ti.com (Chris Winemiller)
Subject: Re: Connect a DLL to Visual Smalltalk 3.1
Message-ID: <1996Feb25.035801.3820@ticipa.works.ti.com>
Organization: None
References: <4gauku$qt5@dalesbred.terra.net>
Date: Sun, 25 Feb 1996 03:58:01 GMT
Lines: 170

Jim,

I'm posting to comp.lang.smalltalk rather than answering you in email
because I thought the question and (hopefully) my answer are of
interest to many.

In article <4gauku$qt5@dalesbred.terra.net> jimk@hank.terranet.com (Jim
Kimball) writes:

>I am trying to talk to a 'C' function in a DLL from VS and having
>trouble.
>
>The function prototype is:
>
>func1(char *name, void **handle);

I'll give you an example in VS 3.0.x, which should be the same as in 3.1
(I hope).  Suppose one wishes to call the Winsock function WSAStartup:

    int PASCAL FAR WSAStartup ( WORD wVersionRequested, 
                                LPWSADATA lpWSAData );

Where LPWSAData and WSAData are defined in C like this:

typedef struct WSAData {
        WORD                    wVersion;
        WORD                    wHighVersion;
        char                    szDescription[WSADESCRIPTION_LEN+1];
        char                    szSystemStatus[WSASYS_STATUS_LEN+1];
        unsigned short          iMaxSockets;
        unsigned short          iMaxUdpDg;
        char FAR *              lpVendorInfo;
} WSADATA;

typedef WSADATA FAR *LPWSADATA;

The second parameter to WSAStartup() is a pointer to a WSAData struct. I
created classes named WinsockDLL and WSAData. (Fileout for WSAData is
included at the end of this message.) Here's an example of how
WSAStartup is called:

"Open the Winsock."
d := WSAData new.
ws := WinsockDLL open.

"Start the Winsock, indicating that revision 1.1 is the highest we can use."
result := ws wsaStartup: 16r0101 asParameter data: d asParameter.
result ~= 0 ifTrue: [
    result := ws wsaGetLastError.
    MessageBox warning: 'WSAStartup error: ', result printString].

You can then open an inspector on the 'd' variable and examine its
contents which have been placed there by the WSAStartup() function.

The WinsockDLL>>wsaStartup:data: method is implemented like this:

wsaStartup: versionRequestedInteger data: aWSAData
    "Start up the receiver."

    <api: WSAStartup short struct long>


Here's the fileout for WSAData:

------------------------------- Begin here -----------------------------

ExternalBuffer subclass: #WSAData
  instanceVariableNames: ''
  classVariableNames: ''
  poolDictionaries: ''  !


!WSAData class methods !

inspectorFields
        "Answer the names of the fields contained in this kind of definition."
    ^FieldInspector fields: #(
        wVersion
        wHighVersion
        szDescription
        szSystemStatus
        iMaxSockets
        iMaxUdpDg
        lpVendorInfo
    )!

sizeInBytes
         "Private - Answer the default size in bytes."
    ^398! !



!WSAData methods !

iMaxSockets

    ^self uShortAtOffset: 390.!

iMaxSockets: anInteger

    ^self uShortAtOffset: 390 put: anInteger!

iMaxUdpDg

    ^self uShortAtOffset: 392.!

iMaxUdpDg: anInteger

    ^self uShortAtOffset: 392 put: anInteger!

lpVendorInfo

    ^self uLongAtOffset: 394.!

lpVendorInfo: anInteger

    ^self uLongAtOffset: 394 put: anInteger!

szDescription

    | aString |
    aString := String new: 257.
   1 to: aString size do: [ :i |
        aString at: i put: ( self byteAtOffset: i + 3 ) asCharacter ].
   ^aString trimNullTerminator asNormalizedString!

szDescription: aString

   1 to: aString size do:
     [ :i | self byteAtOffset: (4 + i - 1) put: (aString at: i) asciiValue ].
   ( aString size + 1 ) to: 257 do:
     [ :i | self byteAtOffset: (4 + i - 1) put: 0 ].!

szSystemStatus

    | aString |
    aString := String new: 129.
   1 to: aString size do: [ :i |
        aString at: i put: ( self byteAtOffset: i + 260 ) asCharacter ].
   ^aString trimNullTerminator asNormalizedString!

szSystemStatus: aString

   1 to: aString size do:
     [ :i | self byteAtOffset: (260 + i - 1) put: (aString at: i) asciiValue ].
   ( aString size + 1 ) to: 129 do:
     [ :i | self byteAtOffset: (260 + i - 1) put: 0 ].!

wHighVersion
    ^self shortAtOffset: 2!

wHighVersion: anInteger
    self shortAtOffset: 2 put: anInteger!

wVersion
    ^self shortAtOffset: 0!

wVersion: anInteger
    self shortAtOffset: 0 put: anInteger! !


-------------------------------  End  here -----------------------------

Regards,
Chris
==============================================================
Chris Winemiller               Internet: clw@works.ti.com
Disclaimer: I do not speak for TI.
==============================================================

