This is a bit of an extension on another of my questions. I've got a DLL that is supposed to interface with Game Maker, which uses Double and PChar.
I have to convert my objects to Doubles (references) to pass back and forth with Game Maker.
I have 2 Classes: TBitmap and TWindow. Each implements IBlittable. This means that methods operating on IBlittables can use both, however here's the problem:
Here's how I create them:
{Creation of Bitmaps and Windows}
function CreateBitmap(W, H: Double): Double; STDCall;
var
TBM: TBitmap;
begin
TBM := TBitmap.Create(Floor(W), Floor(H));
CreateBitmap := Double(Integer(TBM));
end;
function GetWindowByHWND(Handle: Double): Double; STDCall;
var
ReturnVal: TWindow;
begin
ReturnVal := TWindow.Create(Floor(Handle));
GetWindowByHWND := Double(Integer(ReturnVal));
end;
And here's how I am trying to operate on them:
function SetPixel(Handle, X, Y, Color: Double): Double; STDCall;
var
<stuff>
begin
Blittable := IBlittable(Floor(Handle)); //This!
<set the pixel>
SetPixel := 0;
end;
When I cast the Floor(Handle) to IBlittable, it segfaults and crashes.
When I cast it to what it previously was (a TWindow or a TBitmap) it works fine. How do I circumvent this problem?
I really don't want to rewrite all the methods specifically (that'd be pretty redundant and lame)
I needed to change the types in the creation functions:
function CreateBitmap(W, H: Double): Double; STDCall;
var
TBM: IBlittable; //See
begin
TBM := TBitmap.Create(Floor(W), Floor(H));
CreateBitmap := Double(Integer(TBM));
end;
function GetWindowByHWND(Handle: Double): Double; STDCall;
var
ReturnVal: IBlittable; //Here too
begin
ReturnVal := TWindow.Create(Floor(Handle));
GetWindowByHWND := Double(Integer(ReturnVal));
end;
Related
Is overloading of implicit type conversion possible for enumerations in Delphi?
program TriState;
type
TTrilean = (trNone = -1, trFalse = 0, trTrue = 1);
TTrileanHelper = record helper for TTrilean
public
class operator Implicit(...)...; //E2123 PROCEDURE, FUNCTION, PROPERTY, or VAR expected
end;
var
v: TTrilean;
begin
v := trNone;
v := True; //Would like to have class operator Implicit here
end.
In the Delphi 10.4.2 documentation I read:
Note: Class and record helpers do not support operator overloading.
I want to program a game and would like to use a component pattern for multiple entities.
In a language with interfaces / type-classes / multiple inheritance there would be no problem.
I want some entities to be updateable but not renderable and some shall be both.
Haskell:
class Updateable a where
update :: Float -> a -> a
class Renderable a where
render :: a -> Picture
class InputHandler a where
handleInput :: Event -> a -> a
I can create a list of things that can be updated.
updateAll :: Updateable a => Float -> [a] -> [a]
updateAll delta objs = map (update delta) objs
In Java/D/... this could be implemented via Interfaces
interface Updateable {
void update(float delta);
}
// somewhere in a method
List<Updateable> objs = ...;
for (Updateable o : objs) {
o.update(delta);
}
Now I am wondering how this can be implemented in nim with multimethods.
Can the existence of a fitting multimethod be expressed in a type?
var objs: seq[???] = #[]
Edit: Added more code and fixed incorrect Haskell example
I'm not sure if this answers your question, but it's worth mentioning.
If you were to store you game objects in separate lists based on type, you could still write a lot of generic logic. Storing objects by type has better better performance because of read-ahead and branch prediction. See this lecture, from a guy who should know what he's talking about: Multiprocessor Game Loops: Lessons from Uncharted 2: Among Thieves.
For instance, if you have defined a texture proc for some of your object types, then you can write a generic draw(t: T) = magicRenderToScreen(texture(t)) proc that will work for all of them. This is also useful if you are implementing resource pools, or any kind of general behaviour really.
You do have to include each affected object type in the render and update loops somehow, but that's usually not a big deal in practice. You can even use a simple macro to make this less verbose, so your render loop simply contains something like renderAll(players, enemies, sprites, tiles)
Generic lists are not straightforward in compiled languages, and nim forces you to see it, which is kind of good when you're working on a game. To have generic lists you typically either have to use pointers and dynamic dispatch, or some kind of union type. I seem to remember that nim used to be able to dispatch to the correct multi-methods from parent object ref's, (which would enable lists to contain several types and dispatch dynamically at runtime) but I'm honestly not sure if that can still be done...?
Someone more knowledgeable please let us know!
The lack of an explicit interface keyword is common question in the Nim community. Taking Araq's answer and applying it to a hypothetical case based on your Java/D snippet we could write something like this:
import strutils # For formatFloat
type
IUpdateable =
tuple[
update: proc(v: float) {.closure.},
show: proc(): string {.closure.}
]
Rounded = ref object
internalValue: float
Real = ref object
a_real_value: float
# Here goes our rounded type.
proc `$`(x: Rounded): string =
result = "Rounded{" & $int(x.internalValue) & "}"
proc updateRounded(x: Rounded, delta: float) =
x.internalValue += delta
proc getUpdateable(x: Rounded): IUpdateable =
result = (
update: proc(v: float) = x.updateRounded(v),
show: proc(): string = `$`(x)
)
converter toIUpdateable(x: Rounded): IUpdateable =
result = x.getUpdateable
# Here goes our Real type.
proc `$`(x: Real): string =
result = "Real{" &
x.a_real_value.format_float(precision = 3) & "}"
proc update_real(x: Real, delta: float) =
x.a_real_value += delta
proc getUpdateable(x: Real): IUpdateable =
result = (
update: proc(v: float) = x.update_real(v),
show: proc(): string = `$`(x)
)
# Here goes the usage
proc main() =
var objs: seq[IUpdateable] = #[]
var a = Rounded()
var b = Real()
a.internalValue = 3.5
b.a_real_value = 3.5
objs.add(a) # works because of toIUpdateable()
objs.add(b.getUpdateable)
for obj in objs:
echo "Going through one loop iteration"
echo "\t", obj.show()
obj.update(0.4)
echo "\t", obj.show()
obj.update(0.4)
echo "\t", obj.show()
main()
# -> Going through one loop iteration
# -> Rounded{3}
# -> Rounded{3}
# -> Rounded{4}
# -> Going through one loop iteration
# -> Real{3.50}
# -> Real{3.90}
# -> Real{4.30}
However, as you can read in that forum thread, depending on what exactly you need interfaces for other approaches may be better. Also, presumably the future way to go are concepts, but as usual the manual is dry and the related unit tests are cryptic so I couldn't manage to translate the previous tuple example to concepts.
If you feel like going for concepts you should ask in the forum directly, but beware, as the manual says, concepts are still in development.
Swift has the same problem and there they use Type Erasure, which is the same as proposed in the previous comments but a bit more strutured. The general pattern in Nim is like this:
#-------------------------------------------------------------
# types
#-------------------------------------------------------------
type C = concept type C
proc name(x: C, msg: string): string
type AnyC = object
name: proc(msg: string): string # doesn't contain C
type A = object
type B = object
#-------------------------------------------------------------
# procs
#-------------------------------------------------------------
proc name(x: A, msg: string): string = "A" & msg
proc name(x: B, msg: string): string = "B" & msg
proc name(x: AnyC, msg: string): string = x.name(msg) # AnyC implements C
proc to_any(x: A): AnyC = AnyC(
name: proc (msg: string): string = name(x, msg) # x captured by proc
)
proc to_any(x: B): AnyC = AnyC(
name: proc (msg: string): string = name(x, msg) # x captured by proc
)
# actually use C
proc print_name(x: C, msg: string) = echo x.name(msg)
#-------------------------------------------------------------
# main
#-------------------------------------------------------------
let a = A()
let b = B()
let cs = [a.to_any(), b.to_any()] # the main goal of most erasure cases
for c in cs:
c.print_name(" erased") # e.g. "A erased"
In this example AnyC implements C, A and B also implement C but more importantly can be converted to AnyC. The Any* types usually contain closures to effectively erase the type and also implement the concept itself by trivial forwarding the arguments.
I wish there was a macro or something that would implement Any* and to_any automatically.
I have the following method where I am searching for the position of a character in a 2D vector.
def findChar(c: Char, levelVector: Vector[Vector[Char]]): Pos = {
var pos: Pos
pos.x = levelVector.indexWhere(row => row.indexOf(c) > 0)
pos.y = levelVector(pos.x).indexOf(c)
pos
}
pos has two integer fields which remember positions on the x and y axis
However, on the line var pos: Pos I am getting the error Block cannot contain declarations.
Why can't the block contain declarations?
Which is the issue with my code?
your problem is that you are writing
var pos:Pos
you should write instead :
val pos = new Pos(...)
Anyway , while reading your code its kind of java written in scala.
if you can be immutable, so be.
in scala you should instantiante your class with the variables. which means you cannot change the state of the class i.e statements like
pos.x = //something
pos.y = //something
is changing the state of the variable pos.
I would reccomend to be immutable
i.e
val x = //something
val y = //something
val newPos = Pos(x,y)
Have fun
Complementing the selected answer, the problem with
var pos: Pos
is that pos was not initialized with anything (thus the "declaration" error).
These two initializations would be valid (for a general case):
var pos: Pos = null
// or
var pos: Pos = new Pos(...)
But in your case, you should use val followed by the constructor
val newPos = new Pos(...)
As mentioned, use immutability in Scala whenever is possible.
If you want to resolve this issue, you need to define var pos: Pos=_ as a global variable in the class and you can call that variable within the function. Please refer to the example below
class ScalaPrintStatement {
var a: Int=_
def main(args: Array[String]): Unit ={
println("The value of a is :"+a)
}
}
Scala will not allow you to declare the variable without initializing within the function because scala does not like mutability, if you just declare the variable. you can immute it whenever you want.
I want to instantiate a package and pass functions to it that overload operators in order to make a Generic Binary Search Tree. Here's the specifications.
bstgen.ads (snippet)
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Deallocation;
GENERIC
type Akey is private;
type TreeRecord is private;
with function "<"(K: in Akey; R: in TreeRecord) return Boolean;
with function ">"(K: in Akey; R: in TreeRecord) return Boolean;
with function "="(K: in Akey; R: in TreeRecord) return Boolean;
PACKAGE BSTGen IS
TYPE St10 IS NEW String(1..10);
TYPE TreePt IS PRIVATE;
PACKAGE EnumIO IS NEW Ada.Text_IO.Enumeration_IO(Akey); USE EnumIO;
driver.adb (snippet)
with Ada.Text_IO; use Ada.Text_IO;
WITH BSTGen;
PROCEDURE Driver IS
IP: Integer := 1;
TYPE Names IS (Resig,Keene,Marsden,Vuijic,Marcus,Gonzalez);
PACKAGE NamesIO IS NEW Ada.Text_IO.Enumeration_IO(Names);
type St10 is NEW String(1..10);
type Customer is
record Name: Names;
PhoneNumber: St10;
end record;
function "<"(K: in Names; R: in Customer) return Boolean is begin
return K < R.Name;
end "<";
function ">"(K: in Names; R: in Customer) return Boolean is begin
return K > R.Name;
end ">";
function "="(K: in Names; R: in Customer) return Boolean is begin
return K = R.Name;
end "=";
PACKAGE IntIO IS NEW Ada.Text_IO.Integer_IO(Integer); USE IntIO;
PACKAGE mybst is NEW BSTGen(Names,Customer,<,>,=); USE mybst;
R, Pt: TreePt;
Name: Names;
Phone: St10;
Status: Boolean;
BEGIN
R := CreateTree;
Pt := R;
However, when I try to compile, this is the output:
driver.adb:24:04: expect subprogram or entry name in instantiation of "<"
driver.adb:24:04: instantiation abandoned
bstgen.ads:19:53: expect discrete type in instantiation of "Enum"
bstgen.ads:19:53: instantiation abandoned
This includes a bunch of errors stating that driver.adb's methods are not visible, which is to be expected as the instantiation of mybst is abandoned. How do I fix this?
In bstgen.ads, you say
PACKAGE EnumIO IS NEW Ada.Text_IO.Enumeration_IO(Akey);
but in the generic formal part you said
type Akey is private;
which means that the compiler can assume very little about the actual type except that equality and assignment are available. It could be a record of hundreds of bytes; it certainly need not be an enumeration.
To ensure that Akey is an enumeration, you need to say
type Akey is (<>);
as in ARM12.5(13).
In driver.adb, you say
PACKAGE mybst is NEW BSTGen(Names,Customer,<,>,=);
which should read
PACKAGE mybst is NEW BSTGen(Names,Customer,”<“,”>”,”=“);
Do you know why when declaring local const vars, the script cannot compile?
Sorry, I know very little pascal and cannot figure out why this is not working!
This example (see function CircleArea) shows that my syntax should be fine.
http://www.tutorialspoint.com/pascal/pascal_quick_guide.htm
This is what I am trying to do:
//---placed within [Code]
procedure MyLog(const _functionName, _msg: String);
begin
Log(_functionName + '(): ' + _msg);
end;
function MyExec(const _filename, _params, _dir: String): Boolean;
const // <--- compilation fails in this line!
MethodName = 'MyExec';
var
ResultCode: Integer;
begin
MyLog(MethodName, _filename);
// ... invoke Exec(), etc. ...
end;
//---
You were trying that right. If Inno Setup were using Pascal it would even work, but since it is based on a custom Pascal Script language with limitation on declaring local constants, you can't do it that way. You must define your constant globally instead:
[Code]
const
MethodName = 'MyExec';
function MyExec(const _filename, _params, _dir: String): Boolean;
var
ResultCode: Integer;
begin
MyLog(MethodName, _filename);
// ... invoke Exec(), etc. ...
end;
You can use #define to define "local" constants and then use ExpandConstant('{#ConstantName}') whenever you need the value of that constant.
function MyExec(const _filename, _params, _dir: String): Boolean;
var
ResultCode: Integer;
begin
#define MethodName 'MyExec'
MyLog(ExpandConstant('{#MethodName}'), _filename);
// ... invoke Exec(), etc. ...
end;
Note that the constant isn't actually local, because it is just a preprocessor definition. So the functions after MyExec could refer to the constant as well, which might be a potential cause of error (but isn't worse than defining a real global constant). You can redefine the same constant in another function or procedure without causing a compile error though.
function MyExec(const _filename, _params, _dir: String): Boolean;
begin
#define MethodName 'MyExec'
MyLog(ExpandConstant('{#MethodName}'), _filename);
end;
function MyExec2(const _filename, _params, _dir: String): Boolean;
begin
// if you forget to put the next line, it will log 'MyExec'!!!
#define MethodName 'MyExec2'
MyLog(ExpandConstant('{#MethodName}'), _filename);
end;
For added safety, you might want to #undef the "local" constant at the end of the function, in which case InnoSetup would cause a compile error if you'd try to reference it in the next function.
function MyExec(const _filename, _params, _dir: String): Boolean;
begin
#define MethodName 'MyExec'
MyLog(ExpandConstant('{#MethodName}'), _filename);
#undef MethodName
end;
function MyExec2(const _filename, _params, _dir: String): Boolean;
begin
// Forgot to define MethodName, but InnoSetup will cause an error
// "undeclared identifier: MethodName".
MyLog(ExpandConstant('{#MethodName}'), _filename);
end;