Fully managed Scintilla Control

Topics: Developer Forum, Project Management Forum
Apr 3, 2009 at 1:12 PM
Edited Apr 3, 2009 at 1:16 PM
Hello,

Does anybody hate native dependencies? (coping binaries to System32, DLL hell...)

Excellent Scintilla .NET control depends on native Scintilla DLL today, but it is definitely not requiered! Using MC++ we can easily compile Scintilla codebase to mixed DLL and use on its own (say declare base ScintillaControl class wich implements INativeScintilla interface). All other things could be left in ScintillaNet C# project - it is mutch better to code in C# after all...

In that case we also get two DLLs: ScintillaBase.dll (mixed assembly with native implementation and base classes) and ScintillaNet.dll (fully managed and powered WinForms control). But it is much easier to distribute (we can use GAC or private assembly) and support.

This configuration works fine for me (I can share a test project if somebody is interested in it), but the next step will be to combine this assemblies to one - that will be really great to have a single DLL to reference! Well, actually we can do that :) (The really great tool from Microsoft Research - ILMerge - can not handle native code, so we have to do it.)

One of the possible approach is to compile MC++ project as a module, not an assembly. Than this module could be linked with the C# sources into a single assembly. Visual Studio does not support modules for the С# projects, but the C# compiler do - so we have to use build script.

The other (hard) way is to compile C# sources into an intermediate assembly and than convert it to a module (there are no tools to do that, but it is definitely possible - the only difference is an assembly manifest embedded into assembly - it should be removed). Than this module could be linked with the C++ sources -Visual Studio does support that scenario.

What do you think?

Sincerely yours,
Vadim (skipin@digdes.com)
Coordinator
Apr 3, 2009 at 3:00 PM
It's a great idea, but it's actually not the first time we've considered it. I did some research into the topic about 18 months ago and found that it's not that easy to do. As you mentioned, there are no official Microsoft tools available and so a custom build tool would have to be written from scratch.

In the end, I lost my interest after I spent some time speaking to the System.Data.SqlLite developers. They were building mixed assemblies and found that it was such a headache to get working on some platforms that they were considering abandoning the idea. I think they're still using mixed assemblies, but I don't think we have the personnel on the Scintilla.NET project to maintain such a build.

If you are interested in pursing it, I would welcome any build tools or other suggestions you have.
Coordinator
Apr 3, 2009 at 6:35 PM
I'm in complete agreement with Jacob. It sounds great in theory but every time any of us has tried it the complexities have made this kind of implementation impractical. If you manage to pull it off however I'd be willing to take a closer look.
Apr 3, 2009 at 7:07 PM
Edited Apr 3, 2009 at 7:15 PM
Hmm... yes, it is not as simple as it could be. As I note earlier we could not use the ILMerge to produce a single assembly as it does not support non-IL code.
I dig into the msbuild internals and discover that it is quite simple to build a netmodule from the C# project in Visual Studio - all we have to do is it to manually edit the ScintillaNet.csproj file and change "<OutputType>Library</OutputType>" to "<OutputType>Module</OutputType>". After that we could link it together and... produce a multifile assembly :) I really think that it is better than have the native DLL dependency, but...

Another way is to build pure managed Scintilla assembly. The main part of Scintilla codebase compiles with /clr:pure without problems, but the win32\ScintillaWin.cxx implements some native COM interfaces and should be rewrited.
Apr 5, 2009 at 9:32 AM
Edited Apr 5, 2009 at 9:33 AM
Ok, finally I manage to get it right.

Now I have a solution (without any external build scripts) wich can be used to build the ScintillaNet.dll assembly with emdedded C++ Scintilla library and without any external dependencies. The only undocumented feature I use is the <OutputType>Module</OutputType> trick.

The proposed solution looks this way:
1. ScintillaLib - native C++ static library contains the Scintilla Control implementation (configuration is mine, sources borrowed from scintilla.org project).
2. ScintillaNet - managed C# library contains the WinForms Scintilla Control wrapper (the only changes I made is to build it as netmodule).
3. Scintilla - mixed C++ library used to link all parts together into a single assembly.

I hope that my work will be usefull for your project.
Apr 5, 2009 at 9:58 AM
Edited Apr 6, 2009 at 9:27 AM
Forget to say it: insteed of calling LoadLibrary() to initialize native Scintilla library now we have to do something like this:

Type type = Type.GetType("ScintillaNet.NativeScintilla", true);
MethodInfo method = type.GetMethod("RegisterClasses", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod);
method.Invoke(null, null);

The NativeScintilla class defined in MC++ library can call Scintilla_RegisterClasses(), Scintilla_ReleaseResources() and Scintilla_DirectFunction() directly.

UPDATE: I made some trick with [MethodImpl(MethodImplOptions.ForwardRef)] and we do not need reflection any more. Also I add support for x64 configuration (and it works just fine in my tests).
Coordinator
Apr 9, 2009 at 10:08 PM
Would you like to post the sample binaries and project files? I'm not promising we would add it to the Scintilla.NET sources, but I would be interested in taking a look.


Jacob

Apr 10, 2009 at 5:48 AM
I am not sure what the best way to share code with Codeplex, so I just create a new workitem.
See http://scintillanet.codeplex.com/WorkItem/View.aspx?WorkItemId=21996 for the code attached.