How to link C# and C++ assemblies into a single executable?

不问归期 提交于 2019-11-28 06:04:47

The following is a Nant build-script that does exactly what you (and me) wanted (if I read your wanting right that is xD).

Some of it is missing (like some variables, that aren't really needed), but it turned out to actually be fairly easy to achieve.

This shows the cl/csc and linker-flags you need to be able to merge a mixed and a managed assembly. Also, as an added "bonus" all internal classes/methods/fields etc. is visible within the entire new assembly, meaning that they cross the boundary of the project.

    <delete file="${tmp.cpp}" />
    <foreach item="File" property="filename">
        <in>
            <items basedir="${basedir}/SpotiFire.LibSpotify">
                <include name="**.h" />
            </items>
        </in>
        <do>
            <echo message="#include &quot;${filename}&quot;&#10;" append="true" file="${tmp.cpp}" />
        </do>
    </foreach>

    <cl outputdir="${build.obj}" options="/clr /LN">
        <sources basedir="${basedir}/SpotiFire.LibSpotify">
            <include name="*.cpp" />
            <include name="${tmp.cpp}" asis="true" />
            <exclude name="AssemblyInfo.cpp" />
        </sources>
    </cl>

    <csc target="module" output="${build.obj}/SpotiFire.netmodule">
        <modules basedir="${build.obj}">
            <include name="tmp.obj" />
        </modules>
        <references refid="all_refs" />
        <sources basedir="${basedir}/SpotiFire.SpotifyLib">
            <include name="**.cs" />
        </sources>
    </csc>

    <link output="${build.dir}/${name}.dll" options="/LTCG /FIXED /CLRIMAGETYPE:IJW /NOENTRY /DLL">
        <sources basedir="${build.obj}">
            <include name="*.obj" />
            <include name="*.netmodule" />
            <include name="${basedir}/libspotify.lib" asis="true" />
        </sources>
        <arg value="/DEBUG" if="${build.debug == 'true'}" />
    </link>

Your business case is very similar to SQLite, so the same approach should work for you. Basically they insert the managed assembly into the unmanaged dll as a separate data section. They are then able to p/invoke the unmanaged dll from the managed dll in the normal way. It is also possible to dynamically link to the unmanaged code in the dll.

In order to be correctly merged in, program.netmodule should be indicated in linker two times, in input list and as the parameter in ASSEMBLYMODULE option.

So the whole command line will will be as follows:

link /LTCG /CLRIMAGETYPE:IJW /ENTRY:MixedLanguageDemo.Program.Main /SUBSYSTEM:WINDOWS /ASSEMBLYMODULE:program.netmodule /OUT:MixedLanguageDemo.exe managedmessageprovider.obj messageprovider.obj program.netmodule

After this command line, program.module types should be merged into MixedLanguageDemo.exe. You can always check what gets into your resulting assembly with .NET reflectors, like ILSpy or Telerik.

Happy coding.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!