Re: Calling D from C++

2011-07-19 Thread Loopback

On 2011-07-19 05:46, Johann MacDonagh wrote:


What is the best method to accomplish this, and are there any
limitations with this method (do I have to allocate the class with
malloc instead etc.)?


Your C++ class Base is not compatible with your D Foo class. The
v-tables are not guaranteed to be identical. I'm not even sure if D's
thiscall is the same as C++'s thiscall. It's just not going to work.
Most languages don't support this. This is why we use C bindings.
Everyone supports C ;)

Now, you can do something like this:

struct Foo
{
int x;
float y;
}

extern(C) void* GetNewFoo()
{
// Note: Don't use new here otherwise the GC may clean it up
return cast(void*) core.memory.GC.malloc(Foo.sizeof);
}

extern(C) float Foo_DoSomething(Foo* foo)
{
return foo.x + foo.y;
}

extern(C) void FreeFoo(Foo* foo)
{
core.memory.GC.free(foo);
}

I haven't tried this, but something like this should work. Structs are
inherently compatible between languages. Of course, you won't be able to
do any kind of polymorphism.

Does this help?


Very interesting!

This might help depends; are you able to have structures with functions?
Are they still analogous if you implement them?

Also, how come the class-interface inheritance didn't work to
communicate with C++. Is the Interface to C++ doc's outdated?

Calling D Virtual Functions From C++

http://www.digitalmars.com/d/2.0/cpp_interface.html


Re: Calling D from C++

2011-07-19 Thread Loopback

On 2011-07-19 12:39, Loopback wrote:

On 2011-07-19 05:46, Johann MacDonagh wrote:


What is the best method to accomplish this, and are there any
limitations with this method (do I have to allocate the class with
malloc instead etc.)?


Your C++ class Base is not compatible with your D Foo class. The
v-tables are not guaranteed to be identical. I'm not even sure if D's
thiscall is the same as C++'s thiscall. It's just not going to work.
Most languages don't support this. This is why we use C bindings.
Everyone supports C ;)

Now, you can do something like this:

struct Foo
{
int x;
float y;
}

extern(C) void* GetNewFoo()
{
// Note: Don't use new here otherwise the GC may clean it up
return cast(void*) core.memory.GC.malloc(Foo.sizeof);
}

extern(C) float Foo_DoSomething(Foo* foo)
{
return foo.x + foo.y;
}

extern(C) void FreeFoo(Foo* foo)
{
core.memory.GC.free(foo);
}

I haven't tried this, but something like this should work. Structs are
inherently compatible between languages. Of course, you won't be able to
do any kind of polymorphism.

Does this help?


Very interesting!

This might help depends; are you able to have structures with functions?
Are they still analogous if you implement them?

Also, how come the class-interface inheritance didn't work to
communicate with C++. Is the Interface to C++ doc's outdated?

Calling D Virtual Functions From C++

http://www.digitalmars.com/d/2.0/cpp_interface.html

I noticed that function seems to work functions with structures.
Are there any restrictions worth knowing or is it just like any other
structure when D and C++ communicate?

Can I have private variables, public, properties etc?

And just not to forget, why the C++ and interface class didn't work?


Re: Calling D from C++

2011-07-18 Thread Loopback

On 2011-07-17 22:51, Johann MacDonagh wrote:

On 7/17/2011 3:53 PM, Loopback wrote:

On 2011-07-17 21:45, Loopback wrote:

Hello!

As of my understanding you can write usable c libraries in D by using
extern(C). The problem is that I haven't found any other threads asking
the same question about C++ (since extern for c++ exists as well). So
I have two questions, is it possible to write a dll in D usable in c++
code, and if the answer is yes, are there any restrictions?

Am I forced to use explicit memory handling, or can this be handled by
the garbage collection internally by the dll etc?


Sorry for mentioning this a bit late but noticed this now;
http://www.digitalmars.com/d/2.0/cpp_interface.html

Although if someone has own experiences or something interesting to say
about the matter, please do.


I think you're going to be better off defining your D routines as
extern(C) and then defining the C++ headers as __cdecl (for Windows of
course). C++ can, of course, link against libraries using cdecl.

If you write your D DLL with the normal DllEntry (this came from VisualD):

import std.c.windows.windows;
import core.dll_helper;

__gshared HINSTANCE g_hInst;

extern (Windows)
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
switch (ulReason)
{
case DLL_PROCESS_ATTACH:
g_hInst = hInstance;
dll_process_attach( hInstance, true );
break;

case DLL_PROCESS_DETACH:
dll_process_detach( hInstance, true );
break;

case DLL_THREAD_ATTACH:
dll_thread_attach( true, true );
break;

case DLL_THREAD_DETACH:
dll_thread_detach( true, true );
break;
}
return true;
}

Then as soon as your DLL is loaded the D runtime will start. Any memory
allocated in the D DLL will be garbage collected as you'd imagine.
Obviously, it's not going to free any memory allocated in your C++ code ;)


Thank you for your reply!

I've written a C++ wrapper which communicates with D function but I have
stumbled upon an error. With the code win32 DLL code on the digitalmars
webpage (and yours) I receive linker errors:

 Error 42: Symbol Undefined 
_D4core10dll_helper18dll_process_detachFT4core3sys7w

indows7windows6HANDLEbZv

 Error 42: Symbol Undefined 
_D4core10dll_helper18dll_process_attachFT4core3sys7w

indows7windows6HANDLEbPvPvPvPiZb

 Error 42: Symbol Undefined _D4core13thread_helper12__ModuleInfoZ

From my experience ModuleInfo undefined is often caused by not supplying
a required source file to the linker, but since I only use functions
from the library, I shouldn't be required to do that. Any tips?


Re: Calling D from C++

2011-07-18 Thread Loopback

On 2011-07-18 21:59, Andrej Mitrovic wrote:

import core.dll_helper; is outdated, use import core.sys.windows.dll;
And also import core.runtime;


Are there any examples covering these new modules, or are the procedure
the same?


Re: Calling D from C++

2011-07-18 Thread Loopback

On 2011-07-19 00:56, Johann MacDonagh wrote:

On 7/18/2011 5:04 PM, Andrej Mitrovic wrote:

On 7/18/11, Loopbackelliott.darf...@gmail.com wrote:

On 2011-07-18 21:59, Andrej Mitrovic wrote:

import core.dll_helper; is outdated, use import core.sys.windows.dll;
And also import core.runtime;


Are there any examples covering these new modules, or are the procedure
the same?



It's all pretty much the same as the page says. There's a DLL example
in this folder:
\DMD\dmd2\samples\d\mydll


Looks like VisualD's DLL template needs to be updated.

FWIW I was able to compile and link a D DLL with the code I copy pasted
in the other message.

Loopback, do you have Visual Studio on your dev box? If so you should
take a look at VisualD: http://www.dsource.org/projects/visuald

Let us know if you're not able to compile a D DLL.


Thanks for all of your replies!

It seems as if the problem was solved by using core.sys.windows.dll
instead. Although I do have a bit of a problem. As I mentioned earlier
I wanted to make a DLL which C++ applications could interface with.

By making this possible, I have a dll.d file (just as the example) and
a mydll.d file - the file which implements the dll functions. In this
file, I have declared a function like this (testing purpose):

extern(C++) void SetInt(int * foo)
{
*foo = 5;
}

When I compile this program with this DMD command line:
dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def

I get a successful compile, and a DLL file generated. For
some reason, I also get a ATA.lib file, which is exactly
1.00 KB big (any ideas why)?

The problem though, is related to the C++ side. I load the
DLL dynamically using LoadLibraryA function, and then
I try to load the SetInt function using GetProcAddress.

The LoadLibrary function succeeds but the GetProcAddress
function call fails saying that the function could not be
found.

typedef void (*PFGMO)(int*);

void main(int argc, char ** argv)
{
// Function Pointer
PFGMO pFGMO = NULL;

HINSTANCE library;
if((library = LoadLibraryA(C:\\mydll.dll)) == NULL)
throw 1;

bool result = (pFGMO = (PFGMO) GetProcAddress(library, SetInt)) != 
NULL;

// Result is zero (failed)
std::cout  Result:   result;
std::cin.get();
}

How come the procedure address cannot be found and how to solve it?
If of interest, this is the .def file (mydll.def)

LIBRARY mydll.dll
EXETYPE NT
SUBSYSTEM WINDOWS
CODE SHARED EXECUTE
DATA WRITE

When viewing the DLL with PE Explorer (program to explore executable
files) it reports that the number of symbols are zero. Is this related
to the problem perhaps?


Re: Calling D from C++

2011-07-18 Thread Loopback

On 2011-07-19 04:40, Andrej Mitrovic wrote:

You have several problems.

extern(C++) only specifies the calling convention, not the visibility
of the symbol. To export the symbol, list it in a .def file or mark
the function with export in the module itself, ala:

export extern(C++) void SetInt(int * foo) {}

I don't know why, but if you use a .def file instead of `export` the
function will be exported as a C function with no name mangling.

Anyway, use a .def file like the one below and pass it to DMD while
compiling the DLL, and it should be exported with that name (and
change the string mydll.dll of course):

LIBRARY mydll.dll
DESCRIPTION 'My DLL written in D'
EXETYPE NT
SUBSYSTEM   WINDOWS
CODEPRELOAD DISCARDABLE
DATAWRITE

EXPORTS
 SetInt


ATA.lib is probably the autogenerated import library which is useful
for implicit linking.

Seems as if this fixed it, thank you!

I want to ask though how I am supposed to go about to enable class
communication. For example; if I define a interface, and inherit this
interface in a class, C++ can use these class functions by defining
a analogous class (instead of interface) with virtual functions.

If I create a class dynamically on the heap (in my dll), and then
make a function that c++ can call to receive this object, how should
I proceed then?

extern(C++) interface Base
{
int Test();
}

class Foo : Base
{
public:
extern(C++) int Test() { return 5; }
}

export extern(C++) void GetObject(Base base)
{
Foo temp = new Foo;
base = Foo;
}

This is just a example to explain what I want to accomplish. One problem
with this code, is that a memory exception is thrown on the C++ side if
this function is called, whenever I use the new operator. Is this
because it's a export/extern function?

// C++ Code
class Base
{
public:
virtual int Test(void);
};

What is the best method to accomplish this, and are there any
limitations with this method (do I have to allocate the class with
malloc instead etc.)?


Calling D from C++

2011-07-17 Thread Loopback

Hello!

As of my understanding you can write usable c libraries in D by using
extern(C). The problem is that I haven't found any other threads asking
the same question about C++ (since extern for c++ exists as well). So
I have two questions, is it possible to write a dll in D usable in c++
code, and if the answer is yes, are there any restrictions?

Am I forced to use explicit memory handling, or can this be handled by
the garbage collection internally by the dll etc?


Re: Calling D from C++

2011-07-17 Thread Loopback

On 2011-07-17 21:45, Loopback wrote:

Hello!

As of my understanding you can write usable c libraries in D by using
extern(C). The problem is that I haven't found any other threads asking
the same question about C++ (since extern for c++ exists as well). So
I have two questions, is it possible to write a dll in D usable in c++
code, and if the answer is yes, are there any restrictions?

Am I forced to use explicit memory handling, or can this be handled by
the garbage collection internally by the dll etc?


Sorry for mentioning this a bit late but noticed this now;
http://www.digitalmars.com/d/2.0/cpp_interface.html

Although if someone has own experiences or something interesting to say
about the matter, please do.


Static Destructors called early

2011-07-15 Thread Loopback

Hi!

I'm having a pretty big mess just because my static destructors are
called before my non-static destructors. Now my question is; is this
related only to win32 applications where one uses runtime.terminate?

The problem is that I am using external libraries, and in one of these
cases you initialize the library and later on release it. I initialize
and release the library in static de-/constructors. The external library
I use is a sound library (FMOD). I have a sound class which uses library
functions which in turn needs the library to be *initialized* and not
*released*, when called. In the sound class, I release the sound file
in the destructor, but this fails because the static destructor (which
releases the library itself) has already been called, and therefore all
library function calls are invalid.

Are there any workarounds or solutions? And is it absolutely necessary
to use the runtime initialize and terminate functions, since it works
without any problems in a normal (non-win32) application.

From what I know, static de-/constructors are called when the main
function exits, but does it occur when the runtime, terminates when
using a win32 application?


Re: Problems with static linking of c libraries

2011-07-14 Thread Loopback

You need to convert the libraries to OMF format from COFF.
These are some tools which can do this:

Coffimplib: http://www.digitalmars.com/ctg/coffimplib.html
Coff2OMF: http://www.digitalmars.com/ctg/coff2omf.html
ObjConv: http://www.agner.org/optimize/objconv.zip


Re: Problems with static linking of c libraries

2011-07-14 Thread Loopback

On 2011-07-14 17:06, Danny Arends wrote:

Wow THANX,
Using the COFF2OMF tool at least got me a step further, now it finds and 
accepts the lib files,
however, it now fails with the following error:

OPTLINK (R) for Win32  Release 8.00.12
Copyright (C) Digital Mars 1989-2010  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
lapack.lib(lapack)  Offset B24AEH Record Type 009D
  Error 16: Index Range
--- errorlevel 1

Any suggestions, on how to fix this error ?


My own success have varied depending on which tool that I have used.
COFF2OMF seems to be the one most appropriate with old libraries (such
as VC++ 6.0 and earlier). Coffimplib only works with a few libraries,
(in my own experience) and I have had least success with this tool,
whilst objconv works in most cases. I would recommended to try them
all and see which one that works best for you. If none of them works,
try to use them on different compiled libraries (the one's on the
website and the one's that you have compiled locally etc..).


Re: String Appender Fails (Memory Allocation Failure)

2011-07-14 Thread Loopback

Anybody got an idea?


Re: String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

On 2011-07-14 01:11, Loopback wrote:

Hello!

I've been working on a project where I had to do all memory handling
explicitly because no destructors were called. When I got too tired
of the explicit memory handling I decided to trace what was causing
this error. After hours of code stripping I had gotten myself a
small concrete sample which could demonstrate the error.

Now to the point; I create a program using WinMain as entry point. The
program template i use, is identical to the win32 template on the
D-Website. If you have used this template you know that all user code
goes within the function myWinMain. In this function I declare a class
named Foo. When I create this class an empty constructor is called, and
then the function myWinMain returns.

Now the program calls Runtime.terminate, which is supposed to take
care of the memory garbage and etc. This does not work. The terminate
function call throws an Error, Memory Allocation Failure.
This failure originates in the 'Foo' destructor, which in turn creates
a appender object of type string. My question is; how come this throws
an error?

Not to forget the important part:

// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

// For appender
import std.range;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE 
hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

// If you use Exception object instead here, the program fails
	// silently without any MessageBox of any kind. The program, in this 
case quits

// automatically after about 7-12 seconds, without any destructors 
called.
// If you instead use Error object to catch the error, a message pops
// up saying, Memory Allocation Failure, why?
catch (/*Exception*/Error o) // catch any uncaught exceptions
{
		MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);

result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR 
lpCmdLine, int nCmdShow)

{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
}

~this()
{
// This line causes memory allocation failure
auto writer = appender!string();
}
}


String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

Hello!

I've been working on a project where I had to do all memory handling
explicitly because no destructors were called. When I got too tired
of the explicit memory handling I decided to trace what was causing
this error. After hours of code stripping I had gotten myself a
small concrete sample which could demonstrate the error.

Now to the point; I create a program using WinMain as entry point. The
program template i use, is identical to the win32 template on the
D-Website. If you have used this template you know that all user code
goes within the function myWinMain. In this function I declare a class
named Foo. When I create this class an empty constructor is called, and
then the function myWinMain returns.

Now the program calls Runtime.terminate, which is supposed to take
care of the memory garbage and etc. This does not work. The terminate
function call throws an Error, Memory Allocation Failure.
This failure originates in the 'Foo' destructor, which in turn creates
a appender object of type string. My question is; how come this throws
an error?


Re: String Appender Fails (Memory Allocation Failure)

2011-07-13 Thread Loopback

On 2011-07-14 01:17, David Nadlinger wrote:

Currently, no memory can be allocated at all during garbage collection
runs, which is where destructors are usually called.

David


That explains it. Do you know when this feature will be available, if
at all?

Here is another interesting case, where I am using external libraries
(FMOD) in this case.

I have two different cases here, but they have two notable things in
common. Both use WinMain as entry point and they both originate in the
class Foo.

In the first case, I use the class Foo, which has the Sound
class as a private member. If foo omits the call to allocate the sound
class no Memory Allocation Failure occurs. This error is also avoided
if the two lines in the static destructor of sound is omitted:

FMOD_System_Close(m_system);
FMOD_System_Release(m_system);

How come these external functions generates a Memory Allocation Failure
when they use malloc for their memory allocation? Also worth noticing
is that in the non-static destructor FMOD_Sound_Release is called
without any problems, if the two function calls are omitted.

One other thing; how come no Memory Allocation Failure occurs, when
I do not allocate the sound class, since the static de-/constructors
of the class are still called?

In the second case, the exact same functions are called except that
everything takes place in-lined in the Foo constructor.

Case 1: Memory Allocation Failure and Sound destructor is not called.
Case 2: Everything works as expected.
// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

import std.range;
import std.string;

// FMOD
import fmod.fmod;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPSTR lpCmdLine, int nCmdShow)
{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

catch (Error o)
{
MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);
result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
int nCmdShow)
{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
//m_sound = new Sound(rC:\acdc.ogg);
}

~this()
{
MessageBoxA(null, Never Called, Error, MB_OK | 
MB_ICONEXCLAMATION);
}
private:
Sound m_sound;
}

class Sound
{
public:
static this()
{
if(FMOD_System_Create(m_system) != FMOD_RESULT.FMOD_OK)
throw new Error(Failed to create fmod system.);

if(FMOD_System_Init(m_system, 2, FMOD_INIT_NORMAL, null) != 
FMOD_RESULT.FMOD_OK)
throw new Error(Failed to initialize fmod.);
}

static ~this()
{
// Close and release system (omitting these prevents any errors 
from occuring)
FMOD_System_Close(m_system);
FMOD_System_Release(m_system);
}

this(string file)
{
if(FMOD_System_CreateSound(m_system, cast(char *) 
file.toStringz, FMOD_HARDWARE | FMOD_LOOP_OFF, null, m_sound) != 
FMOD_RESULT.FMOD_OK)
throw new Error(Failed to create sound.);
}

~this()
{
// Release Sound
FMOD_Sound_Release(m_sound);
}

private:
static FMOD_SYSTEM * m_system;  
FMOD_SOUND * m_sound;
}// Import WINAPI
import win32.windows;

// Core API
import core.runtime;

import std.range;
import std.string;

// FMOD
import fmod.fmod;

extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPSTR lpCmdLine, int nCmdShow)
{
int result;
void exceptionHandler(Throwable e) { throw e; }

try
{
Runtime.initialize(exceptionHandler);
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, 
nCmdShow);
Runtime.terminate(exceptionHandler);
}

catch (Error o)
{
MessageBoxA(null, cast(char *) o.toString(), Error, MB_OK | 
MB_ICONEXCLAMATION);
result = 0;// failed
}

return result;
}

int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, 
int nCmdShow)
{
Foo foo = new Foo;
return (foo !is null);
}

class Foo
{
public:
this()
{
FMOD_SYSTEM * m_system; 
FMOD_SOUND * m_sound;

if(FMOD_System_Create(m_system) != FMOD_RESULT.FMOD_OK)
throw 

Re: Float Comparison Returns False

2011-07-09 Thread Loopback

On 2011-07-08 04:31, Loopback wrote:

On 2011-07-08 02:28, bearophile wrote:

Loopback:


I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
epsilons but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.


If you want to use floating point values in your programs then you
probably need to know something about floating point representation.
This is a good starting point:
http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel



From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two non-equal values and how make them equal. Perhaps I should use
ints and long instead since they don't seem to suffer from this
problem?


Generally in a program you use floating point values only if you can't
use integral values (and you don't want to go toward fixed point
values, rationals, etc).

Bye,
bearophile

I've looked up both approxEqual and feqrel, and the last one seems most
appropriate, though I cannot use this function without issuing any
errors. If I use the following code:

writefln(Equality: %s, feqrel(m, 1.73205f));

(From the previous example)

I receive this error with the code:
Error: function std.math.feqrel!(float).feqrel has no return statement,
but is expected to return a value of type int
Error: template instance std.math.feqrel!(float) error instantiating

I weren't able to solve this error so if it's of anyone's interest I
used this function instead;

int feqrel(real a, real b)
{
if (a==b) return real.mant_dig;
real diff = fabs(a-b);

ushort *pa = cast(ushort *)(a);
ushort *pb = cast(ushort *)(b);
ushort *pd = cast(ushort *)(diff);

int bitsdiff = ( ((pa[4]0x7FFF) + (pb[4]0x7FFF)-1)1) - pd[4];

if (pd[4]== 0)
{
   diff*=0x1p+63;
   return bitsdiff + real.mant_dig - pd[4];
}
if (bitsdiff0) return bitsdiff+1;
return bitsdiff==0 ? pa[4]==pb[4] : 0;
}

From: http://www.digitalmars.com/d/archives/digitalmars/D/27873.html


Re: Float Comparison Returns False

2011-07-07 Thread Loopback

On 2011-07-07 20:35, Steven Schveighoffer wrote:

On Thu, 07 Jul 2011 14:19:05 -0400, Loopback elliott.darf...@gmail.com
wrote:


Hello!

I've been programming some miscellaneous code and got stuck in an odd
case. While comparing floats, two obviously identical values return
false in comparison.

I am not sure if this is related to float precision or something
similar. This is the code that I have used:

import std.stdio;

void main(string[] args)
{
while(foo()) {}
}

bool foo()
{
static bool ss;
static int loops;
static float m = 0f;

if(m != 1.73205f)
{
m += 0.00500592f;

if(++loops == 346)
ss = true;
}

if(ss)
{
writefln(Variable: %s, m);
writefln(Constant: %s, 1.73205f);
writefln(Equality: %s, m == 1.73205f);

return false;
}

return true;
}

The output of this program is the following:

Variable: 1.73205
Constant: 1.73205
Equality: false

My question is; how come these values compare unequal?


Because they aren't. Just because they are equal to 5 decimal places
(which by the way is an inaccurate printout of their value), does not
mean they are fully equal.

Be very careful when comparing floating point numbers. Generally you
want to use an epsilon to say they are close enough.

-Steve


Thank you for your answers!

I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
epsilons but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two non-equal values and how make them equal. Perhaps I should use
ints and long instead since they don't seem to suffer from this
problem?


Re: Float Comparison Returns False

2011-07-07 Thread Loopback

On 2011-07-08 02:28, bearophile wrote:

Loopback:


I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
epsilons but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.


If you want to use floating point values in your programs then you probably 
need to know something about floating point representation. This is a good 
starting point:
http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel



   From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two non-equal values and how make them equal. Perhaps I should use
ints and long instead since they don't seem to suffer from this
problem?


Generally in a program you use floating point values only if you can't use 
integral values (and you don't want to go toward fixed point values, rationals, 
etc).

Bye,
bearophile

I've looked up both approxEqual and feqrel, and the last one seems most
appropriate, though I cannot use this function without issuing any
errors. If I use the following code:

writefln(Equality: %s, feqrel(m, 1.73205f));

(From the previous example)

I receive this error with the code:
Error: function std.math.feqrel!(float).feqrel has no return statement, 
but is expected to return a value of type int

Error: template instance std.math.feqrel!(float) error instantiating


Constructor call must be in a constructor

2011-07-06 Thread Loopback

Hi!

While implementing and overloading several different operators for my
structure I've got stuck with an error.

As noticed in the attachment, in my opBinaryRight function I mimic the
opBinary (left) operator by instantiating the structure itself to avoid
implementing duplicates of the binary operator overloads.

The opBinaryRight operator is defined as following:

DVector2 opBinaryRight(string op, T)(T lhs) if(Accepts!T)
{
	// Error: template instance vector.DVector2.__ctor!(DVector2) error 
instantiating

return DVector2(lhs).opBinary!op(this);
}

I create an additional DVector2 structure and then calls the opBinary
operator. When creating this DVector2 structure the following
constructor gets called:

this(T)(T arg) if(Accepts!T)
{
static if(isScalar!T)
this(arg, arg);
else
// Error: constructor call must be in a constructor
this(arg.tupleof);
}

As one can clearly see, the constructor call is within a constructor.
Now my questions are; is this a bug with DMD or is it something with my
code example and is there any workarounds/solutions?
import win32.directx.d3dx9 : D3DXVECTOR2;
import win32.windows : POINT;

struct DVector2
{
// Controls that the argument is one of the following types: float, 
DVector2, D3DXVECTOR2, POINT
template Accepts(T) { enum Accepts = is(T == DVector2) || is(T == 
float) || is(T == D3DXVECTOR2) || is(T == POINT); }

// Whether the argument is a float or not
template isScalar(T) { enum isScalar = is(T == float); }

// X and Y Axis
float x = 0f, y = 0f;

// Default Constructor
this()(float x, float y)
{
this.x = x;
this.y = y;
}

// Implement D3DXVECTOR2 and POINT support
this(T)(T arg) if(Accepts!T)
{
static if(isScalar!T)
this(arg, arg);
else
this(arg.tupleof); // Error: constructor call must be 
in a constructor
}

// Binary Operations
DVector2 opBinary(string op, T)(T rhs) if(Accepts!T)
{
enum rx = isScalar!T ?  : .x;
enum ry = isScalar!T ?  : .y;

return DVector2(mixin(x ~ op ~ rhs ~ rx), mixin(y ~ op ~ 
rhs ~ ry));
}

// Right Binary Operator
DVector2 opBinaryRight(string op, T)(T lhs) if(Accepts!T)
{
return DVector2(lhs).opBinary!op(this); // Error: template 
instance vector.DVector2.__ctor!(DVector2) error instantiating
}

// Assign Operator
ref DVector2 opAssign(T)(T rhs) if(Accepts!T)
{
static if(isScalar!T)
x = y = rhs;

else
{
x = rhs.x;
y = rhs.y;
}

return this;
}
}

void main(string[] args)
{
DVector2 test = DVector2(0f, 1f);

// This statement leads to the following errors:
// (L28) Error: constructor call must be in a constructor
// (L43) Error: template instance vector.DVector2.__ctor!(DVector2) 
error instantiating
// (L70) Error: instantiated from here: opBinaryRight!(+, DVector2)
test = test + DVector2(2f, 1f); // Error: instantiated from here: 
opBinaryRight!(+, DVector2)
}

Re: Operator Overloading and boilerplate code

2011-07-05 Thread Loopback

On 2011-07-05 03:11, Ali Çehreli wrote:

On Tue, 05 Jul 2011 02:44:03 +0200, Loopback wrote:


I've researched a bit though I still haven't come up with a solution.
Since the problem lies within (the most simple) constructor, I tried to
modify it for another outcome. If I supplied a generic parameter to the
pre-constructor the Cannot evaluate at compile time message
disappeared but two new errors appeared instead.

This is what I modified:

this()(float x, float y, float z) =  this(T)(float x, float y, float z)

If I use this code instead, I get two other errors appearing:

Error: template test.DVECTOR2.__ctor(T) does not match any function
template declaration

This error and another one (individual to each statement) appears in the
following code statements:


Error: template test.DVECTOR2.__ctor(T) cannot deduce template function
from argument types !()(float,float)
DVECTOR2 m_zoom = DVECTOR2(2f, 2f);

Error: template test.DVECTOR2.__ctor(T) cannot deduce template function
from argument types !()(immutable(float),const(float)) immutable
DVECTOR2 m_UP_DIR = DVECTOR2(0f, 1f, 0f);


Here is a simple form of the same problem:

struct S
{
 this(T)(double d)
 {}
}

void main()
{
 auto o = S(1.5);
}

Error: template deneme.S.__ctor(T) does not match any function template
declaration
Error: template deneme.S.__ctor(T) cannot deduce template function from
argument types !()(double)

The compiler is right: What should T be there? int? string? MyClass?

I've realized again that I don't know how to specify the template
parameter for the constructor. The following attempt fails as the
compiler thinks S itself is a template:

 auto o = S!string(1.5);

Error: template instance S is not a template declaration, it is a struct

And if I try to be smart after the error message, this seg faults the
compiler:

 auto o = S.__ctor!string(1.5);

Ali

Hmm... Interesting. Thank you for clarifying and explaining that!

I guess supplying T to the constructor when the parameters are already
known to avoid compiler errors is not a solution then. Seems to me as if
its only aggravates things.

Though is there no solution nor any workarounds for this problem? I've
attempted to use two different types of constructors and both appeared
to be very limited, and I do not believe that this is the case.

If you use a generic constructor is there no possible way to use it in
cases where immutable and const is involved? Or is there a page
that I have missed perhaps?
struct DVECTOR2
{
// Controls that the parameter is a valid type
template Accepts(T) { enum Accepts = is(T == DVECTOR2) || is(T == 
float) || is(T == D3DXVECTOR2) || is(T == POINT); }

// Whether the parameter is a float or not
template isScalar(T) { enum isScalar = is(T == float); }

// The Variables
float x = 0f;
float y = 0f;

// Default Constructor
this()(float x, float y)
{
this.x = x;
this.y = y;
}

// Float Constructor
this()(float xy) { this(xy, xy); }

// Implement D3DXVECTOR2 and POINT support
this(T)(T arg) if(Accepts!T  !isScalar!T) { this(arg.tupleof); }

// Inverse the vector
DVECTOR2 opUnary(string op)() if(op == -) { return DVECTOR2(-x, -y); }

// Binary Operations
DVECTOR2 opBinary(string op, T)(T rhs) if(Accepts!T)
{
enum rx = isScalar!T ?  : .x;
enum ry = isScalar!T ?  : .y;

return DVECTOR2(mixin(x ~ op ~ rhs ~ rx), mixin(y ~ op ~ 
rhs ~ ry));
}

// Right Binary Operator
DVECTOR2 opBinaryRight(string op, T)(T lhs) if(Accepts!T) { return 
DVECTOR2(lhs).opBinary!op(this); }

// Assign Operator
ref DVECTOR2 opAssign(T)(T rhs) if(Accepts!T)
{
static if(isScalar!T)
x = y = rhs;

else
{
x = rhs.x;
y = rhs.y;
}

return this;
}

// In-Place Assignment Operators
ref DVECTOR2 opOpAssign(string op, T)(T rhs) if(Accepts!T) { 
return(this.opAssign(opBinary!op(rhs))); }

// Cast Operators (to D3DXVECTOR2 and POINT)
T opCast(T)() if(Accepts!T  !isScalar!T) { return T(x, y); }
}

unittest
{
// This fails, saying that the expression cannot be
// evaluated at compile time.
immutable DVECTOR2 test = DVECTOR2(0f, 1f, 0f);
}

Re: Operator Overloading and boilerplate code

2011-07-05 Thread Loopback

On 2011-07-05 18:05, Ali Çehreli wrote:

I don't want to look like brushing off the problem but having many
constructors make the code complicated. For example, it may be confusing
which constructor gets called here:

 auto d = DVECTOR2(1.5);


That might be true. I just did what felt most convenient, but perhaps
that is not always the solution.


D2 has changed the meaning of inout to mean something like templatize
just the mutable/const/immutable qualification of the parameter but it
is not implemented fully yet. Look at Inout Functions on the Functions
spec:


Foolish of me to forget about inout functions. Is there any possibility
though that the inout tag offers a solution to my initial problem,
where the constructor couldn't be evaluted at compile time?

It feels a bit redundant if you would have to have unique constructors
just to enable support for immutable instantiations of your class, or
perhaps this lies within the use of templates and their generic
parameters?

I've been at this problem for over a day and it feels awful to be left
with no choice and move away from using templates and instead having
walls of boilerplate code just to support immutable and const
instantiations of one's structure.


Re: Operator Overloading and boilerplate code

2011-07-04 Thread Loopback

I've researched a bit though I still haven't come up with a solution.
Since the problem lies within (the most simple) constructor, I tried to
modify it for another outcome. If I supplied a generic parameter to the
pre-constructor the Cannot evaluate at compile time message
disappeared but two new errors appeared instead.

This is what I modified:

this()(float x, float y, float z) = this(T)(float x, float y, float z)

If I use this code instead, I get two other errors appearing:

Error: template test.DVECTOR2.__ctor(T) does not match any function 
template declaration


This error and another one (individual to each statement) appears in the
following code statements:


Error: template test.DVECTOR2.__ctor(T) cannot deduce template function 
from argument types !()(float,float)

DVECTOR2 m_zoom = DVECTOR2(2f, 2f);

Error: template test.DVECTOR2.__ctor(T) cannot deduce template function 
from argument types !()(immutable(float),const(float))

immutable DVECTOR2 m_UP_DIR = DVECTOR2(0f, 1f, 0f);


Re: Operator Overloading and boilerplate code

2011-07-03 Thread Loopback

Thank you!

How excellent you handled the boilerplate code. Works perfectly fine as
well, except one little thing. I cannot declare this DVECTOR2 structure
immutable because the compiler complains saying this:

Error: variable __ctmp1485 cannot be read at compile time
Error: cannot evaluate __ctmp1485.this(0F,1F,0F) at compile time

As I mentioned before, I am new to D and I do not understand why the
compiler cannot evaluate the expression at compile time.

One more thing which I also am wondering is how opCast really works.
To trigger opCast you need to do an explicit cast (tell me if I'm wrong)
and when you do this, does it also work for cases like this:

cast(D3DXVECTOR2) vector2

Does this code trigger the defined opCast (vector2 is a DVECTOR2
structure in this case) or do I have to define a new opCast in
cases where the address operator is used or is the compiler
able to distinguish the cases and cast opCast before the address
operator is evaluated?

struct DVECTOR2
{
// Controls that the parameter is a valid type
	template Accepts(T) { enum Accepts = is(T == DVECTOR2) || is(T == 
float) || is(T == D3DXVECTOR2) || is(T == POINT); }


// Whether the parameter is a float or not
template isScalar(T) { enum isScalar = is(T == float); }

// The Variables
float x = 0f;
float y = 0f;

// Default Constructor
this()(float x, float y)
{
this.x = x;
this.y = y;
}

// Float Constructor
this()(float xy) { this(xy, xy); }

// Implement D3DXVECTOR2 and POINT support
this(T)(T arg) if(Accepts!T  !isScalar!T) { this(arg.tupleof); }

// Inverse the vector
DVECTOR2 opUnary(string op)() if(op == -) { return DVECTOR2(-x, -y); }

// Binary Operations
DVECTOR2 opBinary(string op, T)(T rhs) if(Accepts!T)
{
enum rx = isScalar!T ?  : .x;
enum ry = isScalar!T ?  : .y;

		return DVECTOR2(mixin(x ~ op ~ rhs ~ rx), mixin(y ~ op ~ rhs ~ 
ry));

}

// Right Binary Operator
	DVECTOR2 opBinaryRight(string op, T)(T lhs) if(Accepts!T) { return 
DVECTOR2(lhs).opBinary!op(this); }


// Assign Operator
ref DVECTOR2 opAssign(T)(T rhs) if(Accepts!T)
{
static if(isScalar!T)
x = y = rhs;

else
{
x = rhs.x;
y = rhs.y;
}

return this;
}

// In-Place Assignment Operators
	ref DVECTOR2 opOpAssign(string op, T)(T rhs) if(Accepts!T) { 
return(this.opAssign(opBinary!op(rhs))); }


// Cast Operators (to D3DXVECTOR2 and POINT)
T opCast(T)() if(Accepts!T  !isScalar!T) { return T(x, y); }
}


Operator Overloading and boilerplate code

2011-07-02 Thread Loopback

Hi!

I've made a two dimensional vector structure (x, y) which is very
primitive, the only real thing that I want to do with this structure
is support for nearly all operators and support for D3DXVECTOR2 and
POINT structures.

While writing this structure the boilerplate code has steadily
increased. Since I am new to D I mainly wanted to ask if there are any
solutions to prevent this amount of boilerplate code with mixins etc...

The unittest, also, fail to compile. When I am trying to use the
in-place assignment operator the compiler complains saying this;

Error: function dx.directx.DVECTOR2.opAssign (ref const const(DVECTOR2) 
rhs) is not callable using argument types (DVECTOR2)
Error: cannot implicitly convert expression (this.opBinary(rhs)) of type 
DVECTOR2 to float
Error: template instance dx.directx.DVECTOR2.opOpAssign!(+) error 
instantiating


The first two errors origins from the last opOpAssign operator (taking
a float argument) whilst the last error is from the test += 2f
statement.

struct DVECTOR2
{
float x = 0f;
float y = 0f;

this(float x, float y)
{
this.x = x;
this.y = y;
}

this(float xy)
{
this.x = xy;
this.y = xy;
}

// Implement D3DXVECTOR2 support
this(const ref D3DXVECTOR2 vec)
{
this.x = vec.x;
this.y = vec.y;
}

// Implement POINT support
this(const ref POINT pnt)
{
this.x = pnt.x;
this.y = pnt.y;
}

// Return a inverse vector
DVECTOR2 opUnary(string op)() if(op == -) { return DVECTOR2(-x, -y); }

// The Binary Operators
	DVECTOR2 opBinary(string op)(DVECTOR2 rhs) { return DVECTOR2(mixin(x 
~ op ~ rhs.x), mixin(y ~ op ~ rhs.y)); }
	DVECTOR2 opBinary(string op)(D3DXVECTOR2 rhs) { return 
opBinary!op(DVECTOR2(rhs)); }
	DVECTOR2 opBinary(string op)(POINT rhs) { return 
opBinary!op(DVECTOR2(rhs)); }
	DVECTOR2 opBinary(string op)(float rhs) { return 
opBinary!op(DVECTOR2(rhs)); }


// Right Operators Support
	DVECTOR2 opBinaryRight(string op)(DVECTOR2 lhs) { return 
lhs.opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(D3DXVECTOR2 lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(POINT lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(float lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }


// Assignment Operator
	ref DVECTOR2 opAssign(const ref DVECTOR2 rhs) { x = rhs.x; y = rhs.y; 
return this; }
	ref DVECTOR2 opAssign(const ref D3DXVECTOR2 rhs) { return 
(this.opAssign(DVECTOR2(rhs))); }
	ref DVECTOR2 opAssign(const ref POINT rhs) { return 
(this.opAssign(DVECTOR2(rhs))); }

ref DVECTOR2 opAssign(float rhs) { return 
(this.opAssign(DVECTOR2(rhs))); }

// In-Place Assignment Operators
	ref DVECTOR2 opOpAssign(string op)(DVECTOR2 rhs) { return 
(this.opAssign(opBinary!op(rhs))); }
	ref DVECTOR2 opOpAssign(string op)(D3DXVECTOR2 rhs) { return 
(this.opAssign(opBinary!op(rhs))); }
	ref DVECTOR2 opOpAssign(string op)(POINT rhs) { return 
(this.opAssign(opBinary!op(rhs))); }


// This is where the two first errors occur
	ref DVECTOR2 opOpAssign(string op)(float rhs) { return 
(this.opAssign(opBinary!op(rhs))); }


// Operator Casts
	D3DXVECTOR2 opCast(T)() if(is(T == D3DXVECTOR2)) { return 
D3DXVECTOR2(x, y); }
	POINT opCast(T)() if(is(T == POINT)) { return POINT(cast(int) x, 
cast(int) y); }

}

unittest
{
DVECTOR2 test = DVECTOR2(2f, 2f);
test += 2f; // This is where the last error occurs

assert(test.x == 4f);
}


Re: Win32 Application Error

2011-06-29 Thread Loopback

Please ignore. Sadly I hadn't learned the D reference just enough and I
did not realize that the base destructor of a class is still called.


Win32 Application Error

2011-06-28 Thread Loopback

Hi!

I've recently been using D to program win32 executables. On the official
D site (d-programming-language.org) there is a template of how a basic
win32 executable is supposed to be. In this template you are supposed to
initialize and terminate the D runtime. If I understand correctly this
runtime is related to garbage collection and static con- and
destructors.

This snippet below from my own code works perfectly fine at my
other computer (though both of my computers uses the exact same OS;
win7 x64 Ultimate).

My problem occurs when I terminate the runtime. With one of my computers
it works flawlessly, while on this computer the application hangs up on
exit. I've debugged the code located it to where I terminate the
runtime. The application stops responding completely. Now the
interesting part is that the application do close, but the process still
runs. So you do not notice it at all practically, until you check in the
task manager. The process ends after a while, varying from 5 seconds to
50 seconds.

This is what happens if I press the close button (in the corner). If I
close the program with PostQuitMessage(0) instead, the application is
still visible but a Program is not resonding appears. This also
happens at runtime terminate.

So my question is; how should I avoid these process still running and
program not responding errors?

(if worth mentioning, the program itself works perfectly fine, it is
just at exit the program 'bugs').

The code below is my main.d file.

// Win32 Imports
import win32.windef;
import win32.winuser;

// STDCore Includes
import core.runtime;
import std.utf;

// Custom Includes
import cwindow;
import global;

// Application Entry Point
extern (Windows) int WinMain(HINSTANCE hInstance, HINSTANCE 
hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{
int result;

void exceptionHandler(Throwable e) { throw e; }

try
{
// Start Runtime
Runtime.initialize(exceptionHandler);

// Create Application
CWindow wndw = new CWindow(hInstance);

// Control Object
if(wndw !is null)
result = 1;

// Terminate Runtime
Runtime.terminate(exceptionHandler); // It always crashes here
}

catch(Throwable o)
{
		MessageBoxW(null, o.toString().toUTF16z, Error, MB_OK | 
MB_ICONEXCLAMATION);

result = 0;
}

return result;
}


Re: Win32 Application Error

2011-06-28 Thread Loopback

Thank you for your reply!

I do not use multi-threading so it is not related to that. Though I do
have located the error. It seems as if the application only hangs/delays
application exit, when I load a texture file with DirectX. To be
specific, the function in this case is D3DXCreateTextureFromFileExW.

I still do not see though why the terminate function call fails. Since
the same code works on my other computer. I've also used DirectX debug,
and checking all HRESULTs (success or failure basically). The DirectX
debug output does not display any errors nor warnings and all HRESULTs
returns successfully. The texture loaded with the function does also
work flawlessly, likewise the free memory functions for the textures.

Below is the code that I use for loading and releasing textures:

class (...)

IDirect3DTexture9 LoadTexture(IDirect3DDevice9 device, string fileName, 
D3DXIMAGE_INFO * info = NULL)

{
// Check if the texture has already been allocated
IDirect3DTexture9 * pTexture = (fileName in m_textures);

// Return it then
if(pTexture !is null)
return *pTexture;

// If not, create a new one
IDirect3DTexture9 texture;

// Allocate It
	if(FAILED(D3DXCreateTextureFromFileExW(device, fileName.toUTF16z, 
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, 
D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT, 0, info, NULL, texture)))

return null;

// Return it
return m_textures[fileName] = texture;
}

void Destroy()
{
foreach(string key; m_textures.keys)
m_textures[key].Release();
}

// The associative array
IDirect3DTexture9[string] m_textures;



Re: Win32 Application Error

2011-06-28 Thread Loopback

One more thing, would it perhaps help if I supplied a delegate to
the terminate function, since that may output debug messages?

I would gladly try it but I am not sure how this supplied delegate is
supposed to be.

Also want to mention that the initialize functions returns successfully.


Convert const(GUID)* to GUID*

2011-06-25 Thread Loopback

Hello!

I've recently been working with DirectInput using the win32 API Binding
at dsource.org. This wrapper has been working perfectly fine until I
started using GUID constants defined in win32.directx.dinput8.

The directx function DirectInput8Create takes these parameters:
HRESULT DirectInput8Create(HINSTANCE, DWORD, GUID*, void**, IUnknown);

For the GUID* (3rd) parameter, I specify the IID_IDirectInput8 constant.
This is defined in the dinput8 file as follows:
const GUID IID_IDirectInput8A = {...};

If I supply this constant to the DirectInput8Create function the
compiler complains saying that it cannot convert const(GUID) to GUID*.
If I instead use IID_IDirectInput8 (as a reference) I get the
Cannot convert const(GUID)* to GUID* instead. So my question is; how
do I solve this?


Re: Undefined function, even though imported

2011-06-14 Thread Loopback

Well, I solved the linker error by specifying imports in the
.def file. The pathetic thing was that the def file was invalid
just because I had a newline, or at least it worked without it.

So my final .def file looks like this:

EXETYPE NT
SUBSYSTEM WINDOWS
IMPORTS
_Direct3DCreate9@4 = d3d9.Direct3DCreate9

Thanks for all help!


WindowsAPI Binding - Linker Errors

2011-06-13 Thread Loopback

Hello!

I've been test programming win32 applications recently, and since the 
phobos win32 library is so limited, I decided to download and test the 
WindowsAPI Binding 
(http://www.dsource.org/projects/bindings/wiki/WindowsApi). Using the 
latest snapshot (as of this writing) I receive the following linker 
errors when I compile:


Error 42: Symbol Undefined _D5win328winerror12MAKE_HRESULTFbkkZi
(MAKE_HRESULT is undefined).

These are my imports: win32.mmsystem, win32.windef, win32.winuser, 
win32.wingdi and win32.directx.d3d9.


The problem lies within the DirectX module. If I do not import it, there 
are no errors. I've taken the d3d9.lib and d3dx9.lib from the DirectX 
SDK and used coffimplib and the linked to them, without success.


These are the libraries I am linking to: gdi32.lib, winmm.lib and d3d9.lib.

Any theories why MAKE_HRESULT is undefined? Have I forgotten to link to 
something?


Undefined function, even though imported

2011-06-13 Thread Loopback

Hi!

Let me begin by saying, I'm sorry if this is caused of some obvious 
error but since I am new to D, I am not aware of all the tricks and 
treats it offers.


I am working with the WindowsAPI binding at dsource.org (though I do not 
believe this is related to the binding itself). However, in my code I 
call the function LOWORD (win32 specific). This function is defined in 
the win32.windef module. Although it is defined there (without any 
encapsulations in version statements or anything similar) I receive this 
error:


Error 42: Symbol Undefined _D5win326windef6LOWORDFkZt (LOWORD undefined)

To solve this I had to copy-paste the exact function directly into my 
own file/module instead. So my question is the following; why do I have 
to copy and paste the function directly in my code when it is clearly 
defined in one of the files I import?


Windef.d attached
/***\
*windef.d   *
*   *
*   Windows API header module   *
*   *
* Translated from MinGW Windows headers *
*   by Stewart Gordon   *
*   *
*   Placed into public domain   *
\***/
module win32.windef;

public import win32.winnt;
private import win32.w32api;

const size_t MAX_PATH = 260;

ushort MAKEWORD(ubyte a, ubyte b) {
return cast(ushort) ((b  8) | a);
}

uint MAKELONG(ushort a, ushort b) {
return cast(uint) ((b  16) | a);
}

ushort LOWORD(uint l) {
return cast(ushort) l;
}

ushort HIWORD(uint l) {
return cast(ushort) (l  16);
}

ubyte LOBYTE(ushort w) {
return cast(ubyte) w;
}

ubyte HIBYTE(ushort w) {
return cast(ubyte) (w  8);
}

template max(T) {
T max(T a, T b) {
return a  b ? a : b;
}
}

template min(T) {
T min(T a, T b) {
return a  b ? a : b;
}
}

const void* NULL = null;
alias ubyte   BYTE;
alias ubyte*  PBYTE, LPBYTE;
alias ushort  USHORT, WORD, ATOM;
alias ushort* PUSHORT, PWORD, LPWORD;
alias uintULONG, DWORD, UINT, COLORREF;
alias uint*   PULONG, PDWORD, LPDWORD, PUINT, LPUINT;
alias int WINBOOL, BOOL, INT, LONG, HFILE, HRESULT;
alias int*PWINBOOL, LPWINBOOL, PBOOL, LPBOOL, PINT, LPINT, LPLONG;
alias float   FLOAT;
alias float*  PFLOAT;
alias CPtr!(void) PCVOID, LPCVOID;

alias UINT_PTR WPARAM;
alias LONG_PTR LPARAM, LRESULT;

alias HANDLE HGLOBAL, HLOCAL, GLOBALHANDLE, LOCALHANDLE, HGDIOBJ, HACCEL,
  HBITMAP, HBRUSH, HCOLORSPACE, HDC, HGLRC, HDESK, HENHMETAFILE, HFONT,
  HICON, HINSTANCE, HKEY, HMENU, HMETAFILE, HMODULE, HMONITOR, HPALETTE, HPEN,
  HRGN, HRSRC, HSTR, HTASK, HWND, HWINSTA, HKL, HCURSOR;
alias HANDLE* PHKEY;

static if (WINVER = 0x500) {
alias HANDLE HTERMINAL, HWINEVENTHOOK;
}

alias extern (Windows) int function() FARPROC, NEARPROC, PROC;

struct RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
}
alias RECT RECTL;
alias RECT*   PRECT, LPRECT, PRECTL, LPRECTL;
alias CPtr!(RECT) LPCRECT, LPCRECTL;

struct POINT {
LONG x;
LONG y;
}
alias POINT POINTL;
alias POINT* PPOINT, LPPOINT, PPOINTL, LPPOINTL;

struct SIZE {
LONG cx;
LONG cy;
}
alias SIZE SIZEL;
alias SIZE* PSIZE, LPSIZE, PSIZEL, LPSIZEL;

struct POINTS {
SHORT x;
SHORT y;
}
alias POINTS* PPOINTS, LPPOINTS;

enum : BOOL {
FALSE = 0,
TRUE  = 1
}


Re: Undefined function, even though imported

2011-06-13 Thread Loopback

Thanks for your answer!

Seems like supplying with the file location solved the problem, though I 
still wonder about one thing. The imported module is located in 
c:/d/dmd2/import/win32/windef.d and I have used this command line to 
the DMD compiler: -Ic:/d/dmd2/import/. Shouldn't the linker/compiler 
be able to solve this on its own then?


Re: Undefined function, even though imported

2011-06-13 Thread Loopback

On 2011-06-13 23:51, Jonathan M Davis wrote:

On 2011-06-13 14:44, Loopback wrote:

Thanks for your answer!

Seems like supplying with the file location solved the problem, though I
still wonder about one thing. The imported module is located in
c:/d/dmd2/import/win32/windef.d and I have used this command line to
the DMD compiler: -Ic:/d/dmd2/import/. Shouldn't the linker/compiler
be able to solve this on its own then?


-I just tells it where to look for imports, not what to link. The linker never
links in anything unless you explicitly tell it to - either by having it
directly on the command line or in DFLAGS (usually set by dmd.conf on Linux
and sc.ini or Windows). Phobos is listed in dmd.conf/sc.ini, which is why it
gets linked in. If it wasn't there, you'd have to list it explicitly too.

- Jonathan M Davis

Can you modify the sc.ini so the linker automatically checks a specific
directory for imports? Let's say for example this I have my imports in
c:/d/dmd2/import/, can I implement this in sc.ini so I don't have to
worry about these specific linker errors again?

I tried adding -I%@P%\..\..\import (custom import directory) in sc.ini
without success.

Another question I'm wondering is; if I include a module and tell its
location explicitly to the linker, do I then also have to tell the
linker the location of all local imports this file have as well?


Re: Undefined function, even though imported

2011-06-13 Thread Loopback

Thanks for all the answers! Seems like rdmd did the trick.
I don't see why this isn't built in to dmd though, or does it cause
overhead when you are using rdmd? Benefits, Drawbacks?

I've also stumbled upon an additional error with the win32 DirectX
bindings, but this seems D related actually. When I compile any code
at all (with rdmd) which imports win32.directx.d3d9 and uses the
function Direct3DCreate9, the linker issues this warning:

Error 42: Symbol Undefined _Direct3DCreate9@4

It is shown even though I'm using rdmd and I have linked to d3d9.lib
(other functions like CreateDevice and Present still works though).
To solve this error, I did some searching and it seems like I'm not
the first one with this problem. I got 2 hits:

http://www.digitalmars.com/d/archives/digitalmars/D/learn/1475.html
http://www.dsource.org/forums/viewtopic.php?p=13971sid=d43d05620f0c3a30758a326394ac2e26

Both of these links says that the problem is solved by adding
_Direct3DCreate9 to imports. I've tried to do this by linking to a
.def file with this content (without success, same error is still
issued).

EXETYPE NT
SUBSYSTEM WINDOWS

IMPORTS
_Direct3DCreate9@4=d3d9.Direct3DCreate9

I also tried this code but pragma build_def seems deprecated:

pragma(build_def, IMPORTS);
pragma(build_def, _Direct3DCreate9@4=d3d9.Direct3DCreate9);

So am I doing something wrong with the def file or am I perhaps
supposed to use another pragma?

Thanks in advance!