Re: Calling D from C++
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++
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++
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.)?
Re: Calling D from C++
On 2011-07-19 00:56, Johann MacDonagh wrote: On 7/18/2011 5:04 PM, Andrej Mitrovic wrote: On 7/18/11, Loopback 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++
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++
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++
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.
Calling D from C++
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?
Static Destructors called early
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: String Appender Fails (Memory Allocation Failure)
Anybody got an idea?
Re: Problems with static linking of c libraries
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: Problems with static linking of c libraries
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: String Appender Fails (Memory Allocation Failure)
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(r"C:\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)
Re: String Appender Fails (Memory Allocation Failure)
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)
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: Float Comparison Returns False
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 (bitsdiff>0) 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
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
Re: Float Comparison Returns False
On 2011-07-07 20:35, Steven Schveighoffer wrote: On Thu, 07 Jul 2011 14:19:05 -0400, Loopback 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"?
Float Comparison Returns False
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?
Constructor call must be in a constructor
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
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
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
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
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
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
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.
Re: Win32 Application Error
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.
Re: Win32 Application Error
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;
Win32 Application Error
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; // STD&Core 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; }
Convert const(GUID)* to GUID*
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
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!
Re: Undefined function, even though imported
On 2011-06-14 18:30, Trass3r wrote: Am 14.06.2011, 02:43 Uhr, schrieb 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 No one does ;) Haha well it would be nice if at least one soul knew and could explain.. 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 So the other functions in d3d9 work but only this one doesn't? Yeah, that's why I think this i related to D somehow and not the binding itself. Though I'm just guessing. 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 ^^ This can't work cause the linker knows nothing about D modules. You'd have to use the correct D mangled name. I see your point, but I think the IMPORTS statement refers to the lib file, and the lib file is still C (since D can import c libs). But I still haven't got it to work yet, so I would really appreciate if someone knows what I am doing wrong with the def file/pragma statements!
Re: Undefined function, even though imported
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=13971&sid=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!
Re: Undefined function, even though imported
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: -I"c:/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
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: -I"c:/d/dmd2/import/". Shouldn't the linker/compiler be able to solve this on its own then?
Undefined function, even though imported
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 }
WindowsAPI Binding - Linker Errors
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?