April 19, 2024, 04:17:10 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


declarations in dll

Started by LarryMc, April 10, 2007, 01:31:09 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

Need an example of class, method, member declares in main module of program when class resides inside a dl.

Lets use as an example the "oop_array" example.

In the src used for the dll the following code would reside:
I need to know what needs to be added for "exporting"?
'simple example of using objects in Emergence BASIC
declare import,GlobalAlloc(flags as uint,size as int),uint
declare import,GlobalReAlloc(handle as uint,size as int,flags as uint),uint
declare import,GlobalFree(handle as uint),int
declare import,RtlMoveMemory(dest as int,source as int,size as int)

class IntArray
'the class destructor
declare _IntArray()
'the class constructor
declare IntArray()

'member functions
declare virtual GetAt(pos as int),int
declare virtual SetAt(pos as int,value as int)
declare virtual SetAtGrow(pos as int,value as int)
declare SetSize(int size)
declare GetCount(),int
declare RemoveAll()
'member variables
protected
int m_mem
int m_GrowBy
int m_numItems
int m_allocated
end class

sub IntArray::IntArray()
m_GrowBy = 10
m_mem = GlobalAlloc(0x40,m_GrowBy * 4)
m_numItems = 0
m_allocated = 10
end sub

sub IntArray::_IntArray()
'clean up our object
if(m_mem)
GlobalFree(m_mem)
m_mem = NULL
endif
m_numItems = 0
m_allocated = 0
end sub

sub IntArray :: GetAt(pos as int),int
if pos < m_numItems
return *<int>(m_mem + (pos * 4))
end if
return 0
end sub

sub IntArray :: SetAt(pos as int,value as int)
if(pos < m_allocated)
*<int>(m_mem + (pos * 4)) = value
if((pos+1) > m_numItems)
m_numItems = pos+1
end if
end if
end sub

sub IntArray :: SetAtGrow(pos as int,value as int)
uint temp
int total
if( (pos + 1) > m_allocated)
'calculate how many blocks to allocate
total = (pos+1) - m_allocated
total = (total & m_GrowBy) + 1
total *= m_GrowBy
'Grow the array
temp = GlobalRealloc(m_mem,(m_allocated + total) * 4,0x40)
if(temp)
m_mem = temp
else
'could not reallocate so copy
temp = GlobalAlloc(0x40,(m_allocated + total) * 4)
RtlMoveMemory(temp,m_mem,m_allocated * 4)
GlobalFree(m_mem)
m_mem = temp
end if
m_allocated += m_GrowBy

end if
SetAt(pos,value)
end sub

sub IntArray :: SetSize(size as int)
uint temp
if(size > m_allocated)
temp = GlobalRealloc(m_mem,(size - m_allocated) * 4,0x40)
if(temp)
m_mem = temp
else
temp = GlobalAlloc(0x40,(size - m_allocated) * 4)
RtlMoveMemory(temp,m_mem,m_allocated * 4)
GlobalFree(m_mem)
m_mem = temp
end if
m_allocated = size
end if
end sub

sub IntArray :: GetCount(),int
return m_numItems
end sub

sub IntArray::RemoveAll()
if(m_allocated)
GlobalFree(m_mem)
m_allocated = 10
m_numItems = 0
m_mem = GlobalAlloc(0x40,m_GrowBy * 4)
end if
end sub


Besides the $use "mydll.lbb" what declarations need to be added in order to be able to use the class in the following:
'test program for Intarray class

IntArray ia
for x = 0 to 99
ia.SetAtGrow(x,RAND(100))
next x
print "array has : " + str$(ia.GetCount()) + " items"
print "Press any key to show array contents"
do:until inkey$ <> ""
'now lets show what we did.
for x=0 to ia.GetCount()-1
print str$(ia.GetAt(x))+" ",
next x
print:print
ia.RemoveAll()
print "array now has : " + str$(ia.GetCount()) + " items"
print "Press any key close"
do:until inkey$ <> ""



LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

April 10, 2007, 05:59:02 PM #1 Last Edit: April 10, 2007, 06:03:59 PM by Larry McCaughn
I haven't had any luck with the dll.  If I put the export keyword anywhere it says I can't export something that is already exported.
Without any export keywords the dll src compiles fine.  When I try to make a lib out of the dll it aborts saying no exports.

With the following I can create a static lib and use it without any problem:
the include file:
class IntArray
'the class destructor
declare _IntArray()
'the class constructor
declare IntArray()

'member functions
declare virtual GetAt(pos as int),int
declare virtual SetAt(pos as int,value as int)
declare virtual SetAtGrow(pos as int,value as int)
declare SetSize(int size)
declare GetCount(),int
declare RemoveAll()
'member variables
protected
int m_mem
int m_GrowBy
int m_numItems
int m_allocated
end class

The source for the static lib 'array.lib"
'simple example of using objects in Emergence BASIC
declare import,GlobalAlloc(flags as uint,size as int),uint
declare import,GlobalReAlloc(handle as uint,size as int,flags as uint),uint
declare import,GlobalFree(handle as uint),int
declare import,RtlMoveMemory(dest as int,source as int,size as int)

$include "oop_array dll test.inc"

sub IntArray::IntArray()
m_GrowBy = 10
m_mem = GlobalAlloc(0x40,m_GrowBy * 4)
m_numItems = 0
m_allocated = 10
end sub

sub IntArray::_IntArray()
'clean up our object
if(m_mem)
GlobalFree(m_mem)
m_mem = NULL
endif
m_numItems = 0
m_allocated = 0
end sub

sub IntArray :: GetAt(pos as int),int
if pos < m_numItems
return *<int>(m_mem + (pos * 4))
end if
return 0
end sub

sub IntArray :: SetAt(pos as int,value as int)
if(pos < m_allocated)
*<int>(m_mem + (pos * 4)) = value
if((pos+1) > m_numItems)
m_numItems = pos+1
end if
end if
end sub

sub IntArray :: SetAtGrow(pos as int,value as int)
uint temp
int total
if( (pos + 1) > m_allocated)
'calculate how many blocks to allocate
total = (pos+1) - m_allocated
total = (total & m_GrowBy) + 1
total *= m_GrowBy
'Grow the array
temp = GlobalRealloc(m_mem,(m_allocated + total) * 4,0x40)
if(temp)
m_mem = temp
else
'could not reallocate so copy
temp = GlobalAlloc(0x40,(m_allocated + total) * 4)
RtlMoveMemory(temp,m_mem,m_allocated * 4)
GlobalFree(m_mem)
m_mem = temp
end if
m_allocated += m_GrowBy

end if
SetAt(pos,value)
end sub

sub IntArray :: SetSize(size as int)
uint temp
if(size > m_allocated)
temp = GlobalRealloc(m_mem,(size - m_allocated) * 4,0x40)
if(temp)
m_mem = temp
else
temp = GlobalAlloc(0x40,(size - m_allocated) * 4)
RtlMoveMemory(temp,m_mem,m_allocated * 4)
GlobalFree(m_mem)
m_mem = temp
end if
m_allocated = size
end if
end sub

sub IntArray :: GetCount(),int
return m_numItems
end sub

sub IntArray::RemoveAll()
if(m_allocated)
GlobalFree(m_mem)
m_allocated = 10
m_numItems = 0
m_mem = GlobalAlloc(0x40,m_GrowBy * 4)
end if
end sub

The code for my test program:
[$use "array.lib"
$include "oop_array dll test.inc"

'test program for Intarray class

IntArray ia
for x = 0 to 99
ia.SetAtGrow(x,RAND(100))
next x
print "array has : " + str$(ia.GetCount()) + " items"
print "Press any key to show array contents"
do:until inkey$ <> ""
'now lets show what we did.
for x=0 to ia.GetCount()-1
print str$(ia.GetAt(x))+" ",
next x
print:print
ia.RemoveAll()
print "array now has : " + str$(ia.GetCount()) + " items"
print "Press any key close"
do:until inkey$ <> ""


Just don't know what I'm doing wrong when I try to may a dll and a linking lib.

All Help says:
QuoteWhen designing a class that will be used in multiple source files place the class definitions in an include file and the method implementations in a source file that is part of the project.  There is no need to use GLOBAL or EXTERN when referring to class methods as the compiler automatically handles this.  Just $include the file with the class definitions and add the methods source file to the project.


LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Parker

I'm not sure that it's possible to export class functions right now. However, this hack might work:

For each method you want to export, try putting this outside of the class:
export ClassName@MethodName
for example
export IntArray@IntArray
export IntArray@_IntArray
export IntArray@GetAt
... and so on

obviously you'll need the class definition.

Additionally, for each method you'll need to create a dummy in asm that calls it. You can copy this format:
_asm
IntArray@IntArray:
    jmp [__imp_IntArray@IntArray]
IntArray@_IntArray:
    jmp [__imp_IntArray@_IntArray]
IntArray@GetAt:
    jmp [__imp_IntArray@GetAt]
; ... along with the rest of them
_endasm


Then you'll need to import the symbols:
declare import IntArray@IntArray( )
declare import IntArray@_IntArray( )
declare import IntArray@GetAt( pos as int ),int
'' ... all the required methods

You'll need an import library from the DLL (not a static library build)

It's a bit tedious, and it would be much nicer if the export and import keywords were allowed in class declares:
declare virtual export GetAt( pos as int ),int
...
but that will have to wait until Paul is settled and has more time to deal with it.

LarryMc

Parker,
If I make a static lib from the class code above then I can use the methods without doing anything other that including the class definition in the application soure file and using $use "xxx.lib"

It's just when I try to make a dll, then an import lib that I run into the problem
When I don't add the export keyword then I get an error of "no exports" when I try to make a lib from the dll.
If I do add the export keywork I get errors when I try to make the dll that says can't export an export.

Seems the thing to do is just go ahead and make a static lib and distribute that instead of a dll for people to use in their application.
Larry


Larry

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Parker

I know, that's what I was trying to fix. You have to follow my instructions (notice I do export the functions, it's just hackish. You have to know how class names are handled, which I happen to know). Then you compile a DLL and create the header file and the stub functions in asm.

The first section (the export IntArray@SomeMethod part) goes in the DLL source file(s) as in a normal function.

The second section can be in any source file inside of the project using the DLL/import library. Note though that if you have multiple files, you'll have to make them global. That's easy:
_asm
global IntArray@IntArray
IntArray@IntArray:
    jmp [__imp_IntArray@IntArray]
global IntArray@_IntArray
IntArray@_IntArray:
    jmp [__imp_IntArray@_IntArray]
global IntArray@GetAt
IntArray@GetAt:
    jmp [__imp_IntArray@GetAt]
; ... along with the rest of them
_endasm


The third section goes in the include file that has the class definition.

If you do those three things, you should be able to use the class from a DLL and import library.