Path: news.daimi.aau.dk!glad From: Morten Grouleff Newsgroups: comp.lang.beta Subject: Re: ExternalRecord Date: 04 Sep 1996 11:20:33 +0200 Organization: DAIMI, Computer Science Dept. of Aarhus Univ. Lines: 130 Sender: grouleff@fraxinus.daimi.aau.dk Message-ID: References: NNTP-Posting-Host: fraxinus.daimi.aau.dk Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit To: Claus-Peter Knaut X-Newsreader: Gnus v5.2.39/Emacs 19.30 knaut@bonny.Germany.EU.net (Claus-Peter Knaut) writes: > > Is it possible to build an externalRecord of this > > > typedef struct result_s { > m_data *queryData, > *cursor; > m_fdata *fieldData, > *fieldCursor; > int numRows, > numFields; > } m_result; > > Where m_data is > > typedef struct m_data_s { > int width; > m_row data; > struct m_data_s *next; > } m_data; > > And m_fdata is > > typedef struct m_fdata_s { > m_field field; > struct m_fdata_s *next; > } m_fdata; Yes. As you suggest, you could use the 'ExternalRecord' pattern defined in basiclib/current/external.bet. Do something like this: ================================ ORIGIN '~beta/basiclib/v1.5/betaenv'; INCLUDE '~beta/basiclib/v1.5/external'; -- program:descriptor -- (# m_result: ExternalRecord (# queryData: @Long(# pos::(# do 0->value #)#); cursor: @Long(# pos::(# do 4->value #)#); fieldData: @Long(# pos::(# do 8->value #)#); fieldCursor: @Long(# pos::(# do 12->value #)#); numRows: @Long(# pos::(# do 16->value #)#); numFields: @Long(# pos::(# do 20->value #)#); #); (* I presume that you meant "m_row *data" *) m_data: ExternalRecord (# width: @Long(# pos::(# do 0->value #)#); data: @Long(# pos::(# do 4->value #)#); next: @Long(# pos::(# do 8->value #)#); #); (* This is the external, that you want to call: *) someExternal: External (# resultptr: @Integer; ok: @Boolean; enter resultptr exit ok #); (* If you need to allocate an external from beta, then pass it to C, * use something like this: *) Cfree: External (# ptr: @Integer; enter ptr #); Cmalloc: External (# len,ptr: @Integer; enter len exit ptr #); createExternal_m_result: (# theResult: ^m_result; do &m_result[] -> theResult[]; 24 -> Cmalloc -> theResult.ptr; exit theResult[] #); aResult: ^m_result; aData: @m_data; do createExternal_m_result -> aResult[]; (* Assumes that someExternal initializes the m_result, we give it *) (if (aResult.ptr -> someExternal) then aResult.cursor -> aData.ptr; (* Makes aData point to 'cursor' *) aData.next -> aData.ptr; (* Steps forward in linked list. *) else (* someExternal failed.... *) if) #) ================================ The resulting code is not exactly easy to read... You should try to keep stuff like this in private implementation modules, preferably with an interface that completely hides the fact that the 'objects' are external. you should *never* do anything like the following: (# ctext: [100]@Char; do @@ctext[1] -> aResult.ptr; (* Make aResult represent ctext *) #) The problem is that the garbage-collector can move ctext in memory. And as 'ptr' is just an integer, the pointer is not updated... Instead, use 'Cmalloc' as described above. memory allocated through Cmalloc is not garbage-collected, so you should remember to Cfree it when you no longer need it. (And are sure, that no externals use it either...) Hope this helps. -- mailto:grouleff@daimi.aau.dk (Morten Grouleff)