|
Can you confirm the function definitions/prototypes match in your simwfp.lib and the code where you are using it?
I am a HUMAN. I have that keyword in my name........
_AnsHUMAN_
|
|
|
|
|
Hi,
what I observed is in the declaration and definition the argument of a function is LPTSTR*
but the compiler is checking for unsigned short*. Is this might cause any problem?
Thanks,
Charan
|
|
|
|
|
sorry it is unsigned short**
|
|
|
|
|
Sounds technically ok to me: the typedef of LPTSTR* will resolve to wchar_t** and if you're using wide characters, i. e. a 16 bit character set then that is equivalent to unsigned short**.
But then again, here might be a possible source of an error, namely when you compiled your code with 8 bit character sets and try to link against code for UNICODE or multibyte char sets, which are 16 bit. Make sure all the parts are compiled with the same settings for your char set, and you are using the correct DLLs/LIBs for that char set.
|
|
|
|
|
Hi,
You are right, I am also assuming that the linker is looking for unicode parameter, and it is unable to find. But I am compiling two static libraries and dynamic library(dll) with Use Unicode Character Set property setting. And I am getting all the errors for the function which is having a parameter unsigned short ** and the function definition containing LPTSTR
Thanks,
Charan
|
|
|
|
|
Thanks for your support, I am missing the setting wchar_t as built in type 'Yes'. This resolved my errors.
|
|
|
|
|
Ok, here is a thing and a playground is C DLL. In a class, i am allocating some memory
(with malloc / HeapAlloc) and copying
some data to it. The this data is returned to a function (which is outside the class), then
this function passes this data to a dll export function, which exports this data to a C#
application. So, as you can see, it is a long way. The question is, what i should do about
that memory, allocated in a class in a dll? I think i should free it somehow, should i?
And all this memory operation thing is kinda complexed, there are pointers to pointers to
pointers to pointers, "destroying" one will corrupt everything on the way forward, so its like
a chain or something. Or should i do something like: write a function (inside dll), which
frees memory after data export, and then, after importing data in an app, call this function?
Thanks.
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
The thing is you have to be careful to free it from the same heap as it's allocated on, or you'll end up in trouble. The general answer to this is to make the module (DLL) that allocated the memory free it. There are many ways to do this but something like this is typical:
Stuff* MakeSomeCrap()
{
Stuff *pStuff = new Stuff();
return pStuff;
}
void FreeStuff(Stuff *pStuff)
{
delete pStuff;
}
Steve
|
|
|
|
|
C# will only free memory allocated by the .net environment. This means that you must free any data that your DLL allocates to avoid memory leaks.
If the data is allocated within the DLL, then it should be freed from the DLL, this is not only good style, but necessary in most cases as the DLL will have a different heap which it allocates from.
You should make a member function of the class to free the memory if possible, however there are many situations where this is not possible when dealing with multiple languages, you can simply export a standard function which calls free or HeapFree from within the DLL.
|
|
|
|
|
Alright guys, thanks for info. So as i see it, to have access to a mem, allocated in dll, so it can bee freed within same dll, i have to make a global variable, like:
wchar_t ****myDB = NULL;
(dllexport)wchar_t ****GetDB()
{
myDB = GetDataBase();
return myDB;
}
(dllexport)void FreeMem()
{
free(myDB);
}
Something like this maybe?
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
If you want to pass blocks of memory around between modules then make sure that whatever module allocated it also frees it. If you don't do that you might end up running into problems with memory being allocated by an allocator specific to one module being returned to another and things going wrong. This means in C calling free from the same library malloc was called from, in C++ it means calling delete from the same module that new was called from [1]. If you're mad enough to be using raw Win32 API calls then whatever called Heap/Global/Local/VirtualAlloc should call Heap/Global/Local/VirtualFree with any required Heap/Global/Local/Virtual[Un]Lock pairs.
There are some other strategies you can use to reduce the chance of an error. One is to write your library so that it doesn't do any memory management. You can do this by either making the client give the library a lump of memory to use or by making the client give a pair of function pointers (functor or interface in C++) to the library - one a pointer to an allocation function, another a poitner to a free/release function. I'd personally go for the first if I were doing cross language calls as the client code can allocate a lump of raw bytes from it's own runtime, give it to a library to play with and then when it's finished consign it to the big bit bucket in the sky. Oh, and make sure that the data structures you're using are plain old data (POD) as different languages have different ideas about what an object is. No idea about C# but Python, for example, can't use C++ objects (and vice versa) without writing a C interface for it.
[1] There are some exceptions - if you're a bit cunning you can get around this rule but it's a good first approximation to say "you allocated it, you release it."
Anyway, hope that helps a bit, if not please shout.
Cheers,
Ash
|
|
|
|
|
Okay, so if it will be, for example, this way (?):
(dllexport)void GetDB(wchar_t ****myDB)
{
myDB = GetDataBase();
}
(dllexport)void FreeMem(void *addr)
{
free(addr);
}
IntPtr myDB = IntPtr.Zero;
GetDB(ref myDB);
FreeMem(myDB);
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
I'd ask if you really need four levels of indirection like that. If you do you'd be just about unique in my experience. Are you sure there's not a structure in there trying to get out?
Ash
|
|
|
|
|
Heh, yeah, i do need such nasty thing. Normally, if i would work all the time in C code, i would use structures in fact, but as i am exporting this whole thing to C# (which is not my primary and in no way beloved language), i stick with wchar_t**** thing, so i know how to easily parse it within C# code without some extra messing around. Export data is a 3D string array, so things went that nasty way
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
Alright, i was so lame.
extern "C"{
__declspec(dllexport)void Stuff(wchar_t *&out)
{
wchar_t *String = L"test string whatever";
out = (wchar_t *)malloc(sizeof(wchar_t *) * wcslen(String) + 1);
wcscpy(out, String);
}
__declspec(dllexport)void FreeMem(void *Ptr)
{
if(Ptr != NULL)
{
free(Ptr);
Ptr = NULL;
}
}
}
[DllImport("testdll.dll")]
public static extern void Stuff(ref IntPtr ptr);
[DllImport("testdll.dll")]
public static extern void FreeMem(IntPtr ptr);
int i = 10000000;
while(i > 0)
{
IntPtr ptr = IntPtr.Zero;
testdll.Stuff(ref ptr);
testdll.FreeMem(ptr);
i--;
}
No crash. Seems to be the best solution so far.
011011010110000101100011011010000110100101101110
0110010101110011
modified on Wednesday, February 2, 2011 7:39 PM
|
|
|
|
|
That is looking good, just a few things I would like to mention:
1. When you modify the value of a parameter, you are only modifying its value within the scope of the function, unless the parameter is passed by reference or you change the value of the pointed to value with a dereference like *p = NULL;
__declspec(dllexport)void FreeMem(void *Ptr) {
if(Ptr != NULL) {
free(Ptr);
}
}
2. sizeof(wchar_t *) * wcslen(String) + 1 is wrong for a few reasons when allocating space for the string.
The +1 needs to be multiplied by the size of each character as well sizeof(wchar_t *) * (wcslen(String) + 1)
Secondly, you need to multiply the number of characters by the size of each character, not the size of the pointer to each character sizeof(wchar_t) * (wcslen(String) + 1)
3. If you allocate a string as an array of wchar_t's rather than a pointer you can get the compiler to hard-code the size in, rather than having to calculate it at runtime.
This only works when the string is known at compile time, as it is in your case.
strlen is a somewhat slow function, it must iterate through every character in the string, check the value of the character and increment a counter. While this is ok if it only happens occasionally, you should prefer to use sizeof() when possible as it gets the compiler to do all this for you.
A similar principal applies for strcpy but to a lesser extent. memcpy can copy the data in chunks rather than 1 character at a time
__declspec(dllexport)void Stuff(wchar_t *&out) {
wchar_t String[] = L"test string whatever";
out = (wchar_t *)malloc(sizeof(String));
memcpy(out, String, sizeof(String));
}
Since you are iterating over this 10,000,000 times (at least in your example) you will notice an increase in performance
Finally, it would be better to return the pointer from Stuff()
__declspec(dllexport)wchar_t *Stuff() {
wchar_t String[] = L"test string whatever";
wchar_t *out = (wchar_t *)malloc(sizeof(String));
memcpy(out, String, sizeof(String));
return out;
}
[DllImport("testdll.dll")]
public static extern IntPtr Stuff();
|
|
|
|
|
Great answer! Thanks very much
011011010110000101100011011010000110100101101110
0110010101110011
|
|
|
|
|
There are two possible solutions:
1. If the data structure in question is trivial and can be trivially allocated and deallocated, delegate the allocation to the caller. this is what many standard functions such as strcpy() do.
2. If the data structure requires some attention upon allocation, or contains arrays of dynamical (and potentially at the time of creation unknown) length, then the above suggested method is preferable, i. e. you allocate the structure and provide a function to deallocate it appropriately at a later time.
Personally I prefere the first method whereever possible, because it is clearer from the point of view of the caller: it is much easier to spot a missing delete or free that should have been paired with a new or malloc, than spotting a missing call to a deallocation function which should be paired with some "get" or "read" function. It may not be implicitely clear that a function that provides some data also allocates the structure (it might just as well provide a pointer to a structure that is allocated and accordingly freed elsewhere!)
|
|
|
|
|
Title says it all. After all my searching I have not been able to find a decent tutorial or sample code that will teach me how to implement and customize a TabControl function in a Visual C++, Win32, Win32 Project environment. A link or download link to this would greatly be appreciated. Please and thank you. 
|
|
|
|
|
You could have put everything into the title itself.
|
|
|
|
|
I think you didn't google it properly. Few of the links I found:
http://www.codeproject.com/KB/tabs/SimpleTab.aspx
http://www.codeguru.com/cpp/controls/controls/tabcontrols/article.php/c7407
http://www.codeproject.com/KB/tabs/AMCustomTabCtrlDemo.aspx
http://www.codeproject.com/KB/tabs/ctabctrlssl.aspx
I haven't gone through the details of the above articles. But after having over look, I can say they might help you to start over (as your problem is not specific. What I've perceived is you just wanna to customize the tab view control).
|
|
|
|
|
I think he was after Win32 API style, not MFC.
|
|
|
|
|
|
If you are wanting to do it with Win32 API and not MFC, I would still suggest checking out the MFC samples that Malli_S linked you to, because it is pretty much the same principal.
See Subclassing a window on MSDN[^]
What you need to do is write your own message procedure for the tab control
WNDPROC g_pOldProc;
LRESULT APIENTRY MyTabProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) {
switch (nMsg) {
case WM_SIZE:
break;
}
return CallWindowProc(g_pOldProc, hWnd, nMsg, wParam, lParam);
}
g_pOldProc = (WNDPROC)SetWindowLong(hTabCtrl, GWL_WNDPROC, (LONG)&MyTabProc);
g_pOldProc = (WNDPROC)SetWindowLongPtr(hTabCtrl, GWL_WNDPROC, (LONG_PTR)&MyTabProc);
You need to restore the old message procedure upon the parents destroy (refer to the sample linked above)
|
|
|
|
|
Hello,
I want to parse the song and video files ....so please tell me anyone how i will do it in MFC.
Ajit K
|
|
|
|
|