Import problem

BlitzMax Forums/BlitzMax Programming/Import problem

_JIM(Posted 2009) [#1]
Hi,

I have a bunch of functions that I want to define in my application, but a few types that I want to hold separate in imported files.

I tried using "Extern" to define the functions inside the imported files, but then I get "duplicate identifier".

Is there any way to have some functions from an imported file point to functions defined in the main file?


beanage(Posted 2009) [#2]
If i understood you right, you might need a third file, like:

MyFunctions.bmx:
Function MyFunction()
..
End Function


MyTypes.bmx:
Type myType
..
End Type
myFunction() 'imported through root source file


MyRootSourceFile.bmx:
Import "MyFunctions.bmx"
Import "MyTypes.bmx"


Hope thats it.


_JIM(Posted 2009) [#3]
Sadly, that won't work because of the way "Import" works. MyTypes.bmx should be able to be compiled by itself. However, it is not aware of the functions in Myfunctions.bmx. That's where I thought declaring them with Extern...EndExtern would solve the problem. But honestly, I have no idea how extern should work... I though it would solve the problem.


Arowx(Posted 2009) [#4]
So in a nutshell your trying to have nested calling functions...

AppLevel.bmx


Level1.bmx


Level2.bmx


The problems you can run into here are cyclic dependencies where a function or type will appear more than once in the source tree.

Two techniques that can get around this that I know of...

1. Use a core import/include file to bring everthing together where needed e.g. at the app level.

2. Turn the more generic code into a module (will also reduce compile time)

3. 1 and 2 are not mutually exclusive.

Hope that helps!


_JIM(Posted 2009) [#5]
Ok, let me try to explain this better:

I've got one type that is generic, but it needs some stuff:

Type MyGenericType
   Method Draw()
      Plot oX(), oY()
   EndMethod
EndType


Those oX and oY functions are dependant on certain things in my application, so they're not generic.

I want to use "Import" to get this type inside the application, but I can't because the functions are not defined for the .bmx file (they are defined outside):

Import "MyGenericType.bmx"

Function oX#()
   Return 10.3
EndFunction

Function oY#()
   Return 15.1
EndFunction


I've tried using extern to define them and got myself a nice bunch of errors that the functions are duplicate (those errors happened when I was actually defining them. I suppose the errors come from the fact that they were already defined by "Extern"... but isn't "Extern" supposed to work just INSIDE that file? SO that if I import the file they're still undefined?


Brucey(Posted 2009) [#6]
A Generic type using non-generic functionality?

There appears to be a minor flaw in your design somewhere, I would say...

btw, Extern is for C/C++ style linking, so that's not likely to work in a hurry.


Why can't you just do something based on what Arowx/Merx ( :-p ) suggests :

main.bmx
Import "common_stuff.bmx" ' this is actually not required because of the following import...
Import "mytype.bmx"

' use some common stuff here


mytype.bmx
Import "common_stuff.bmx"

' use some common stuff in the type


common_stuff.bmx
' define some common stuff here


?


_JIM(Posted 2009) [#7]
Hmm... I'll try that...

I mean generic as in "almost generic" :)


beanage(Posted 2009) [#8]
Thats either a semantic bug or a realy tricky problem. Have you already tried:

MyTypes:
Extern "MyFunctions.bmx"
  Function MyFunction()
End Extern
Type MyType()
  Method RunExternFunctionality()
    MyFunction()
  End Method
End Type


MyFunctions:
Extern "MyTypes.bmx"
  Type MyType
End Extern
Function MyFunction()
  ..
End Function


I'm sure you can EXTERN types! Dunno if that kinda 'nested' Externing works. If you need to import the bmx files before (not having to do so is my last remaining hope)- i've no ideas left :~


beanage(Posted 2009) [#9]
If only your functions were in another one but the root source file!


Mr. Write Errors Man(Posted 2009) [#10]
You might be able to use function pointers.

Type MyGenericType
   Field __fOX()
   Field __fOX()
   Method Draw()
      Plot __fOX(), __fOY()
   EndMethod
EndType


Import "MyGenericType.bmx"

MyGenericTypeInstance.__fOX = oX
MyGenericTypeInstance.__fOY = oY

Function oX()
   print "the battle ox had mighty horns"
   return 1
EndFunction

Function oY()
   print "oy, ship ahead!"
   return 231
EndFunction



matibee(Posted 2009) [#11]
So you have an object that depends on other specific objects.. that's not so unusual but there are several ways of avoiding issues of cyclic dependency.

My favourite way of dealing with these situations is to make your base objects dependant on an interface. They exist in their own little world 'connected' to the outside world via an interface. The object is a toaster, the interface is the toasters plug, and the rest of your code is your house where you want the toaster to work. The toaster will never know about your house, in fact the same toaster is sold all over the world with different plugs.

Function pointers would work, but you may end up with a lot of them. Defining an abstract type that clearly lays out what your base type needs and expects from the outside world makes it easy to maintain.

Here's a base type with an interface that has some abstract methods;


That code will compile fine on it's own. So to use foo..



If your base type is very simple (not worth interfacing) you could make the abstract functions part of foo itself, then define an application specific foo that fills in the gaps. An interface is really useful when it can serve many types and/or functions.