|
I tried profiling the initial stage of my game engine today, and found out that in win32, the timing is not done correctly. The timing per frame is around 0.016-0.017 seconds (all of the time in x64, but only most of the time in win32). In win32, I will get occasional times that are in the order of 10^-5 seconds and also timing that is around 0.033-0.034 seconds (double the usual). It almost seems like the extra long timings are there to compensate for the extra short timings. Now, I've had this issue before, and I know that QueryPerformanceCounter can have issues on multiple cores / processors, as timing may jump from one processor to the other (and you may even end up with negative values when you subtract current minus last tick), which is why I call SetThreadAffinityMask() right before I do the timing and call SetThreadAffinityMask() again after that, to revert to the previous mask. Unfortunately, even with SetThreadAffinityMask(), your thread is not guaranteed to run on the core that you specify -- it is only a hint to the Windows operating system that you'd like to run on a specific core, so I can understand why I would still have issues even then, but what I don't understand is why compiling with the x64 compiler (running Visual C++ 2005 Pro) makes things work perfectly. Is there a fundamental hardware counter difference with win32 vs. x64 (or maybe a way that the timing is done)?
MODIFIED: I should mention, I get 0.016 because of Vsync, which does not allow you to go past 60 fps.
-- modified at 22:39 Friday 22nd June, 2007
|
|
|
|
|
Hi,
I have a question on how to share a class between different projects in VC++.
I have an application project namely ImageApp.exe. It needs another dll project SubFunctions1.dll to run.
In the ImageApp project, I defined and used a class CMyControl. Now, the project SubFunctions1 needs use this class as well.
Since the CMyControl is small, I prefer not putting it in an additional dll project. Is there a better way to share the CMyControl?
|
|
|
|
|
One simple way to gather together small classes is to put them in a common static library (not dll) that you can link with as needed. The code will be linked into your app (or dll), and you do not need to distribute the static library.
|
|
|
|
|
Adding on to what Hans said, you can also export the necessary functions that you need from another class (or the entire class itself) via __declspec(dllexport) and import them from the class where you want to use them with __declspec(dllimport), provided your compiler supports these keywords (MSVC does). One way you can do this is through the following:
#ifndef _EXPORT
#define THEAPI __declspec(dllimport)
#else
#define THEAPI __declspec(dllexport)
#endif
class THEAPI TheClass
{
};
There are a few things you have to do:
1 - Define _EXPORT in the project that you want to export, and don't define _EXPORT in the project where you want to import the class/functions (this can be changed in VC++ project settings under preprocessors).
2 - Include TheClass.h from your main project, where you want to call the functions.
3 - Link with the .lib generated by the exported project from the project where you want to import (these .lib do not contain the full information, only how to link with the DLL).
I believe the above is known as static linking with DLLs, and you must package the DLLs with your executable on deployment. Static linking with the standard .lib will group everything in the .lib with your executable, which is why you can only distribute the executable.
One other way you can link (again with DLLs) is through the use of GetProcAddress() and LoadLibrary() to dynamically load DLLs during runtime, but for the sake of keeping it simple, you might want to just stick with Hans' suggestion or my suggestion above.
|
|
|
|
|
Cyrilix wrote: I believe the above is known as static linking with DLLs
or dynamic linking, early binding
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
I stand corrected.
|
|
|
|
|
I never said I was correct!
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
Hi, Guys,
Great suggestions! I will take all of your points.
Thanks a lot!
Skywalker2008/Stanley Hu
|
|
|
|
|
I have a resource dll into which I placed about 12 32-bit (with alpha) bitmaps. I've been trying to load them from the dll WITHOUT using the dll header but can't figure it out. Can anyone give me some advice/examples of how to do this?
|
|
|
|
|
Maybe the LoadImage() API? I'm not positive ARGB bitmaps are supported - it may require the
LR_CREATEDIBSECTION flag.
GDI+ has a Bitmap class constructor that takes an HINSTANCE and a resource name as well.
LoadLibrary() will get you the HINSTANCE of the resource DLL.
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
Loading the bitmap onto the screen is not the problem... The ARGB's show up just fine with the LoadImage function. The problem is getting the bitmap OUT of the dll. I load the dll but can't get a handle to the bitmap inside. I'm trying to avoid using the header file if I can... For instance, when loading icons from a dll, you can use the ExtractIcon function and it's pretty simple. I'm looking for a way to load a bitmap in this manner.
|
|
|
|
|
So you don't know the name (or ID) of the bitmap you want to extract?
If so, you can enumerate all the bitmap names in the DLL with
EnumResourceNames(hDllModule, RT_BITMAP, ...).
I'm not sure how you determine which one you want...by index I suppose, although I'm not sure
if the order the names are sent to the callback are in a defined order
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
I know the name of them... But when I try to use FindResource or LoadImage (or anything else that gets a handle) I get an error saying that "the specified resource was not found in the image file"
|
|
|
|
|
Ok, didn't you say you had no problem loading them and displaying them with LoadImage()?
What kind of handle are you trying to get?
You should have a valid HMODULE/HINSTANCE for the DLL to start with, or else it will never work.
You can get that by loading the DLL with LoadLibrary();
Then you need a valid name - if it's an integer ID then use the MAKEINTRESOURCE macro to convert the ID to a name "string".
HMODULE hResDLLModule = ::LoadLibrary(_T("c:\\path\myresdll.dll"));
if (hResDLLModule)
{
HBITMAP hBitmap = (HBITMAP)::LoadImage(hResDLLModule, MAKEINTRESOURCE(IDB_BITMAP), ...);
...
::FreeLibrary(hResDLLModule);
}
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
Right... see, I can open the dll using either LoadLibrary or AfxLoadLibrary... that part works fine. I just can't get a handle to the bitmap in the dll. I know the string name of it, but the int isn't defined in the project. So I tried LoadImage(instance, _T("IDB_BITMAP1"),...) but didn't get it. When I try FindResource with that method, it doesn't find the bitmap either.
I got it to work by including the header file from the dll project in my current project. But I don't want to rely on that in case I want to change the images later by just swapping another dll.
|
|
|
|
|
Gotcha. Only icons can be loaded by an index, AFAIK.
By "name" I mean the ID of a resource - all resources have a name - it's a string. The use of
integer IDs is usually (if not always ) easier but to use an integer it has to be cast to
a string pointer (which is what MAKEINTRESOURCE is for). I'm using "name" to mean the ID of the
resource.
You indicated again you don't want to have to know the name of the resource when you load it.
The only way you can do that is enumerate all the bitmaps in the DLL and pick the bitmap you want
somehow. EnumResourceNames() will enumerate all the bitmap names in the DLL - pick the name you
want and load the bitmap with LoadImage() (or whatever method) using that name
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
See, I've never done this before (obviously). I was thinking that the string name of the resource is stored in the dll too, so you could get a handle that way. I basically want to be able to load from xdll a bitmap named IDB_SOMETHING and have the ability to replace that xdll with a different dll that has different bitmaps with the same name.
|
|
|
|
|
I'm following you now
I've never used strings to name a resource so I was wondering how it's done LOL.
In the resource editor, if you put the ID in quotes it will be a string name. In that case you
should be able to pass the name like you did in your sample: _T("IDB_BITMAP")
Make sure that name isn't a #define in the resource header file (resource.h) or it will be
interpreted as the integer it's defined to
To be able to swap DLLs, your new DLLs will need to name the bitmaps the same.
Sorry for all the confusion!
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
lol... will that work??? sounds too easy to be right.... but i guess i'll find out.
|
|
|
|
|
sstainba wrote: will that work???
I tried it first LOL - like I said, I've always just used integers!
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
sstainba wrote: See, I've never done this before
That's why I'm trying to confuse you more! j/k
In the resource editor, when you add a bitmap and set its ID property to something like
IDB_BITMAP1 (or when the editor defines it for you), instead of using IDB_BITMAP1 as-is, it
adds a "#define IDB_BITMAP1 101" entry to resource.h. IDB_BITMAP1 is now a macro, not a string.
So if you try to load a resource using _T("IDB_BITMAP1") as the name, the resource isn't there
because the editor "helped" you by changing IDB_BITMAP1 to an integer.
Therefore, to use string names, when you add the resource, hit F4 to bring up the properties
page for the bitmap and edit the "ID" property to a string in double quotes.
I hope that is more understandable
Mark
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
Ok... that took me a step in the right direction. At least now FindResource is returning a non-NULL handle. I changed the name to include the quotes and it seems to be ok... But I still can't load it onto a button.
HINSTANCE mh = ::AfxLoadLibrary(_T("icons.dll"));
HINSTANCE mb = ::AfxFindResourceHandle(_T("IDB_BITMAP36"), RT_BITMAP);
Both of these return non-NULL handles... but I can't get it to work with LoadImage or LoadBitmap or just casting the mb as an HBITMAP.
I'm trying to set a bitmap field on a button... CButton::SetBitmap(HBITMAP)
Should I maybe use LoadLibrary and FindResource (non-Afx) ? I can't see that it would make a difference... but who knows.
|
|
|
|
|
I think you only need to use FindResource()/AfxFindResourceHandle for obtaining handles to binary
or custom resource types.
For bitmaps, you should use LoadImage(); That should work....are you sure you have the BS_BITMAP
style set on the button (if it's a button resource on a dialog, use F4 to get properties and set
the Bitmap property to true)?
I just tested this and it worked (note that I used ::GetModuleHandle(0) since the bitmap resource
is in my exe file):
HBITMAP hbitmap = (HBITMAP)::LoadImage(::GetModuleHandle(0), _T("MYBITMAP"), IMAGE_BITMAP, 0, 0, 0);
m_BitmapButton.SetBitmap(hbitmap);
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|
Yeah, the button is set correctly. I can load it just fine as long as I include the header and use the int name. I just tried what you've got up there and it's a no go. LoadImage isn't returning a valid handle. Maybe it's because it is in a dll file and not the exe?
|
|
|
|
|
sstainba wrote: LoadImage isn't returning a valid handle.
Is LoadImage() returning NULL? If so, make sure IDB_BITMAP36 isn't defined anywhere else in the
project (most likely resource.h). A "Find in Files..." search in the DLL project for
"IDB_BITMAP36" should only find it once - in the .RC file.
If the name isn't the problem, and LoadImage() is returning NULL, then maybe check the error code
something like this...
HINSTANCE mh = ::AfxLoadLibrary(_T("icons.dll"));
HBITMAP hbitmap = (HBITMAP)::LoadImage(mh, _T("IDB_BITMAP36"), IMAGE_BITMAP, 0, 0, 0);
if (hbitmap)
{
m_BitmapButton.SetBitmap(hbitmap);
}
else
{
DWORD errcode = ::GetLastError();
}
"I'm the Dude. So that's what you call me. You know, that or, uh, His Dudeness, or uh, Duder, or El Duderino if you're not into the whole brevity thing." The Big Lebowski
|
|
|
|
|