Help with polymorphism to create multiplatform lib

BlitzMax Forums/BlitzMax Programming/Help with polymorphism to create multiplatform lib

jondecker76(Posted 2010) [#1]
Hello

I made a Linux webcam access library and it is working how I want it.
I now am going to work on a Windows webcam access library (and eventually hopefully a MAC webcam library)

I know that I am going to have to use polymorphism and a base class to do it right, but I haven't done this yet in BMX and could use a little guidance..

Currently, for Linux, I have a TV4L2 type: (code clipped to simplify)

'V4L2 Linux video device access type
'must Import "v4l2.c" in the main file!!

Extern
	Global dev_name:Byte Ptr
	Global dev_width:Int
	Global dev_height:Int
	Function open_device()
	Function init_device()
	Function start_capturing()
	Function stop_capturing()
	Function uninit_device()
	Function close_device()
	Function grab_one:Byte Ptr()
	
End Extern
Type Tv4l2
	Field pixmap:TPixmap
	Field image:TImage
	Field pixmapMutex:TMutex
	Field imageMutex:TMutex
	Field grabbedPixmap:TPixmap

	Function Create:Tv4l2(dev:String, width:Int, height:Int,isThreaded:Int)
	...
	...
	End Function

	Method open()
		open_device()
		init_device()
		start_capturing()
	End Method

	Method update()
	...
	End Method

	Method Draw(x:Int,y:Int,w:Int,h:Int,mirrored:Byte=True)

	End Method

	Method close()
		stop_capturing()
		uninit_device()
		close_device()
	End Method

Note, the extern part references functions in my "c glue" file, which I must Import at the top of my main program (I can't import it in my type definition file, as Import must be at the top, which sucks!)

I am currently using Tv4l2 directly, but as I said, now I want to work on the cross-platform stuff, and making it out of a base type.
So for now, I have created a simple base class:
'Webcam Module

Type TWebCam
	Field pixmap:TPixmap
	Field image:TImage
	Field pixmapMutex:TMutex
	Field imageMutex:TMutex
	Field grabbedPixmap:TPixmap
	
	Method Open() Abstract
	Method Update() Abstract
	Method Draw() Abstract
	Method Close() Abstract
End Type


Now, I want my Tv4l2 to extend TWebCam (easy enough... Type Tv4l2 extends TWebCam....)


Now I am stuck... I want to call TWebCam.Create() to create a Tv4l2 object if called from linux, or return a TWindowsWebcam if called from Windows. I also need to know how to deal with the import of my external c file and the extern block (which needs to be present only for Linux). I currently do the import in my main project file, as when I put it at the top of my type definition file, it would only work if it was included into the main project file first, as Import must appear at the top of a file...

Anyone care to give me some tips on this?

thanks


plash(Posted 2010) [#2]
Take a look at brl.system. I would recommend doing it like that (import specific code for each platform).


Jesse(Posted 2010) [#3]
you are better of using conditional compiling with the built in compiler directives.
if you are using the Bmax Ide look in the right hand tabs under
Home->Help->Language->Conditional Compiling.
it should be something like this:
?Lenux
type Tv412
... 'code for lenux
end type
?Win32
Type Tv412
... 'code for windows
End Type
?MaxOS
Type Tv412
... 'code for mac
End Type
?

type TWebCam extends Tv412
  Function create:TwebCam()
  End Function
End Type

or instead of using types inside the directives use import "lenuxtype.bmx" and "wintype.bmx" etc. in it's corresponding section


jondecker76(Posted 2010) [#4]
Jesse - Yes, I'm familiar with conditional compiling, and have been using it. But it still doesn't give me the answers I need.

Tv4l2 should extend TWebCam, not the other way around (shouldn't it?) as TWebCam is the base class with abstract methods... Also, I still need to find out the correct way to import my glue file so that the import statement is always at the top of the file (which is sure to break as soon as I include my Type header which has the Include statement in it)

To be more specific:
Tv4l2 should extend TWebCam for the linux version
TWindowsWebcam should extend TWebCam for the windows version
TMacWebcam should extend TWebcam for the mac version
Then I should be able to:
local cam:TWebCam = New TWebCam

to create a new webcam instance... Or am I getting all of this wrong?


Plash - I just looked at brl.system, and I'm still unclear. They are conditional-compiling depending on the platform. But in my case, I need a Type that is extended, with the new extended types being platform specific (Kind of how like TftlkGadget extends TGadget on a Linux system, but a different extended class is used on windows...)


jondecker76(Posted 2010) [#5]
Maybe I should start all over without my own assumptions to avoid confusion (on my part, or anyone else's)

I want to make a cross-platform webcam access library. I have already made a working one for Linux, and will start on the Window's one next. I'm not sure if this should be a module, or just an include file, and I'm unsure of the advantages/disadvantages of each.
I want the code for each platform to be in separate files (I.e. I don't one one big master object with a bunch of ?linux...?win32....etc compiler directives - the code would get way too messy!)
I want to use polymorphism correctly to make the library cross-platform, and easy to use.

For each platform, I want a type with the following methods:
Open()
Close()
Update()
Draw()

Also, I will need to import some c files (different for each platform) and need to know the correct way to import the files and define the functions in an Extern block so that I don't get an error about not using Import at the top of the file (because if a user includes my "WebCam.bmx" file for example, and it isn't on top, then it causes an error that Import must appear at the top of the file)

What is the correct way to do all of this?

thanks


jondecker76(Posted 2010) [#6]
I'm thinking that making this a Module will help with the problem of "Import must be at the top of the file"... I'm going to try this approach


jondecker76(Posted 2010) [#7]
Ok, now on top of all of this, I need to learn how to make a module... I just tried:
- in /mod I created jmd.mod (jmd is my initials)
- in /mod/jmd I created webcam.mod
- in /mod/jmd/webcam.mod I created webcam.bmx
- in /mod/jmd/webcam.mod/webcam.bmx I created a simple file:
SuperStrict

Rem
bbdoc: webcam module
End Rem

Module jmd.webcam

ModuleInfo "Version: 1.0"
ModuleInfo "Author: Jon Decker"
ModuleInfo "License: Blitz Shared Source Code"

ModuleInfo "History: Initial stub created."


Print "Testing..."


but when I build modules, it errors out:
Compiling:webcam.bmx
Compile Error: Identifier 'Print' not found
[/home/jondecker76/BlitzMax/mod/jmd.mod/webcam.mod/webcam.bmx;16;1]
Build Error: failed to compile /home/jondecker76/BlitzMax/mod/jmd.mod/webcam.mod/webcam.bmx


Jesse(Posted 2010) [#8]
polymorphism is not really going to help you much there sense that is not its intended use. If you look at what plash pointed out, it's pretty much the simplest way you should be doing it. You are going to be dealing with one type whether it's in Linux Window or Mac. The best way is to create a type of the same name for each of the platform on a separate file each and use the conditional compiling to load it. It can be the base type and only having the minimal functionality required for each platform with the included abstract generic methods in each. In reality, all you are doing here is just saving some typing as polymorphism is not really need here. If you make the complete type in each of the files using the same name and loading it with conditional compiling it should be as functional as any other method and would not be a better or worst option.

for the module you need to import the required module/s for what you are doing as modules only loads the minimal files required to create an executable. for the "print" you need to "Import BRL.standardIO"


jondecker76(Posted 2010) [#9]
Jesse - so why does MaxGUI take this approach then? It has the basic MaxGUI, and it extends on it for each specific driver. If you look at the graphics system it does the same. So why is it wrong in this application?

Brucey, are you out there?


Jesse(Posted 2010) [#10]
you are talking about different drivers for the "same operating system" not "different operating systems" such as windows with OGL and DirectX and such.


plash(Posted 2010) [#11]
so why does MaxGUI take this approach then? It has the basic MaxGUI, and it extends on it for each specific driver. If you look at the graphics system it does the same.
Indeed, they do work that way, as with the font, audio, and system modules. You're just not seeing the underlaying system at play. brl.system is probably the most concise example.


jondecker76(Posted 2010) [#12]
Jesse - no, each OS is represented this way. I'm positive this is the correct way to do it, I'm just not sure how to do it :(


Jesse(Posted 2010) [#13]
it's going to take you a while but you'll get it sooner or later. ;) sorry, I can't help you much beyond this point as it's all up to you now.


jondecker76(Posted 2010) [#14]
I've been programming for 15 years, trust me, I fully understand the concepts of inheritance, polymorphism and all other aspects of OOP. My problem lies in how to use BMX to accomplish it, as it is a new language to me. So trust me, I do get it, I'm just having some problems applying what I know to this new language.

On a good note, I did get a small module stub to compile for me, and it looks so far like its working as it should. I found the way around the "Import" problem - simply import any file that itself has import at top (if you use include, it instantly breaks the "import must be at the top of the file" rule as the include command itsself keeps the import from being at the top of the file). I've also just successfully extended my base type (using brl.system as a reference, though it extends its driver object which is a bit different than what I 'm trying to accomplish) so it does look like I'm on the right track.. I was hoping someone with some experience in this area could give me some pointers to save some time, but I guess I'll have to keep experimenting my way through it


jondecker76(Posted 2010) [#15]
Ok, having some good progress so far. I have a module made with my linux code supported! I was able to make a base TWebcam class, and extend on it for each different OS like I wanted to. I haven't fully tested it yet, but it built just fine!

Edit: Awesome, finally got to test it and it works great! I now have a "proper" webcam module! Now to add Win32 support!