|
You cannot convert from string to binary by the use of casts. Casts are used to tell the compiler to treat a variable of type X as type Y; however, no conversion of the variable's content will be done.
I must get a clever new signature for 2011.
|
|
|
|
|
Hi,
I am working on VS 2010, I am getting this error, which I didn't able to solve it inspite of adding the linking file(.lib) in the Project Properties -> Link -> Additional Libraries. I am not getting the error in VS6.
what is the reason for this error? I have searched other forums, one of the suggestion I got is it is bug in VS, you need to rename the file, remove it from the project and add it back. Even though I am not satisfied with the suggestion, I tried it, since I have no other option. But it proved invain, I am getting the same error with the new file as well.
Thanks in advance
Charan
|
|
|
|
|
Linker errors arise due to a mismatch in the function declaration/definition. This is because the linker cannot find the exact definition of the function you are trying to use in your code while linking.
You did'nt mention what linker error you are getting. Is it related to some function that you have written or a function that is in a third party library and you are trying to use it?
Please provide more details.
I am a HUMAN. I have that keyword in my name........
_AnsHUMAN_
|
|
|
|
|
Thanks for the reply, I am getting the error for the same function I have written in the lib.
I am trying to link MFC shared dll to static library, I am getting unresolved error while I am compiling shared dll.
|
|
|
|
|
What is the actual symbol that is unresolved? Also show us the definition of the symbol that is unresolved from the .h or .cpp file (you don't need to show us the code, it makes no difference)
You can try a full rebuild of the project, occasionally the compiler gets a little confused.
Also, it is best to use a library that is compiled with the same version of VS that you are linking from.
|
|
|
|
|
There is one more difference in VC6.0 and VS2010 is that library included in VC6.0 is space separated and VS2010 is semi colon separated. Tried it once.
I believe in LOVE AT FIRST SIGHT...
Bcoz I have loved my Mother...
even since I opened my eyes...(ICAN)
|
|
|
|
|
Yes it is right, I converted the project file using VS10, ';' is added automatically by VS10, I didn't have to worry about it.
Sorry for the late replay, I am using 2 static libraries(say A, B) one is dependent on other. Then I am linking MFC shared dll to these 2 static libraries. The error is, it is not finding the function in B which is called from A, while compiling the shared dll.
Thanks,
Charan
|
|
|
|
|
Hi guys,
Sorry If I am confusing you.
I want tobe more clear what I am saying
I have two static libraries A and B (where A is dependent on B)
Now I am compiling dynamic library, which depends on both A and B.
I am getting the error:
simwfp.lib(SimUserErrDlg.obj) : error LNK2001: unresolved external symbol "public: __thiscall CSimString::CSimString(unsigned short const *)" (??0CSimString@@QAE@PBG@Z)
Thanks,
Charan
|
|
|
|
|
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
|
|
|
|
|