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

前端 未结 3 2072
情深已故
情深已故 2020-12-08 11:54

I have VS2008 solution containg a project that generates a C# executable that references a project that generates a dll containing both C++/CLI and unmanaged C++.

I

相关标签:
3条回答
  • 2020-12-08 12:39

    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.

    0 讨论(0)
  • 2020-12-08 12:46

    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>
    
    0 讨论(0)
  • 2020-12-08 12:53

    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.

    0 讨论(0)
提交回复
热议问题