Spence Green

التكرار يعلم الحمار

I am a Ph.D student in Computer Science at Stanford University. In addition to computers and languages, my interests include travel, running, and scuba diving. more...

Archive for the ‘.NET’ Category

Notifying Managed Code of a Native Callback

with 51 comments

Here’s a way for unmanaged code to notify managed code of a callback. The two code types use different calling conventions and the user cannot change the latter’s convention. Instead, use an inner class like this:

__gc classManagedClass
{
private:
__nogc class UnmanagedClass
{
static void __cdecl MyCallback()
{
ManagedClass *mc = ManagedClass::GetClass();
mc->MyFunc();
}
};

ManagedClass *thisClass;

public:
ManagedClass() { thisClass = this; }
static ManagedClass* GetClass() { return thisClass; }

void MyFunc() {}
};

The GetClass() method is a bit unsightly, but elegent nonetheless. The managed code can pass MyCallback to unmanaged code via a function pointer. The unmanaged code calls MyCallback and then MyCallback calls the managed method MyFunc(). This approach is especially useful for IJW DLLs in VC7.

References:

Written by Spence

July 8th, 2005 at 8:38 am

Posted in .NET

Managed Assemblies, IJW, and .h Files

without comments

I solved an intersting problem yesterday, although I still cannot fully explain the solution. My project uses a mixed mode DLL to load some native binaries. I constructed the DLL as a managed assembly so that in my managed code, I can use the following:

#using "mydll.dll"

This statement–It Just Works, or IJW–imports all types. Now I had defined my exception hierarchy in a separate header common to the whole project (not just the mixed dll). The exe and dll thus had the same #include statement. I could both compile and link with this setup. When the DLL threw an exception, though, I encountered a problem. Consider this snippet:


//Exception.h
__gc public MyException : public Exception
{
MyException(String *s) : Exception(s) {}
};

//mydll.dll, built with /LD /clr
#include "Exception.h"
myFunc() {
throw new MyException(S"BLAH");
}

//main.cpp, built with /clr
#include "Exception.h"
try
{
myFunc();
}
catch(MyException *e)
{
//This handler does not catch MyException!
}
catch(Exception *e)
{
Type *t = e->GetType();
Console::WriteLine(t->ToString());
}

The second exception handler illuminated the most elusive aspect of this issue. Although the first handler could not catch the exception, the second catch block showed a MyException type. I have not found a sufficient explanation for this behavior, but it must stem from the interaction of native code and MSIL in the mixed DLL.

Written by Spence

July 6th, 2005 at 7:54 am

Posted in .NET

Mixed Mode DLL and “/Zl”

with 581 comments

I spent 8 hours today debugging a stupid switch set by the VS.NET 2003 AppWizard. I’m trying to wrap some DLLs into a mixed mode DLL for use in some managed code. After laboring with an unmanaged wrapper compiled with /clr, I gave up and tried a “.NET Class Library” AppWizard. Then I added my DLLs, classes, etc. The project compiles correctly and then the linker fails, issuing this error:

LNK2020: unresolved token (0A00002C) ??_7type_info@@6B@

Right. I finally determined that the /Zl switch caused the issue. You will find this setting in Properties->C/C++->Command Line->Additional Options.

Mixed mode DLLs have significant issues in both .NET 1.0 and 1.1.

Written by Spence

June 30th, 2005 at 5:16 pm

Posted in .NET