G
Guest
I have an application that contains both C# and C++. I have a legitimate,
seemingly unavoidable requirement to have an interlock between the C# and the
C++. By this I mean that I have to have a method in C++ that calls a method
in C#, that in turn calls back to the original method in C++. I had this
working in .NET 1.1 by using my final exe as my source of metadata, but it
does not work in 2.0, and I want a proper solution. I have implemented a
small test case, but it is not working and I do not understand why. Here is
what I am doing.
- Make a C++ file containing a function, build it.
- Build a C# file that contains a function, that calls the C++ function. It
uses the metadata from the C++ build.
- Make a new C++ file, with the same name as the old one, that contains a
function with calls the C# function. So it uses the C# metadata.
There are two problems with this approach.
1) When I try and run it, it crashes with the following error:
System.BadImageFormatException: an attempt was made to load a program with an
incorrect format. I do not understand this error, my make file and source
files are below. The call stack showed that it was in the first call from the
C# back into the C++.
2) This is a horrible way of implementing an interlock, surely there must be
a better way of doing it, or a way of eliminating it? I require it because I
have a large volume of legacy code written in C++, and a GUI for it written
in C#, both of which I want to retain. The C++ can call the Get Input
function in C#, which can call back to application code in the C++. But the
application code can in turn call a separate Get Input process in the C#
again. It can go to a maximum depth of 5 or 6 levels at most.
I would appreciate any help that anyone can offer. Thanks.
Here is my make.bat file:
del *.obj
del *.netmodule
rem First, build the one way cpp.
copy cppfu.one cppfu.cpp
cl /LN /clrldsyntax cppfu.cpp
pause
al cppfu.netmodule /platform:x86 /target:lib /out:cppfu.dll
rem Next build the csc.
csc /t:module /r:cppfu.dll csuse.cs
pause
rem Next build the replacement cpp that calls back.
copy cppfu.bot cppfu.cpp
cl /LN /clrldsyntax cppfu.cpp
pause
al cppfu.netmodule /platform:x86 /target:lib /out:cppfu.dll
rem Finally, link it all together.
pause
cl /LN /clrldsyntax macpp.cpp
cl cmain.c macpp.obj /link /nodefaultlib:libcmt
Here is the source code:
Cppfu.one
#include "stdio.h"
namespace CPPFu
{
public __gc class CPPClass{ // ref was __gc.
public: static void FuA(int i)
{
printf("In CPP A %d\n",i);
}
};
}
Csuse.cs
using System;
using CPPFu;
namespace NSinCS
{
public class CSFun
{
public static void CSFunB(int i)
{
Console.WriteLine("In FuB "+i.ToString());
if(i>0) CPPFu.CPPClass.FuA(i-1);
}
}
}
Cppfu.bot
#include "stdio.h"
#using <CSUse.netmodule>
namespace CPPFu
{
public __gc class CPPClass{ // ref was __gc.
public: static void FuA(int i)
{
printf("In CPP A %d\n",i);
if(i>0) NSinCS::CSFun::CSFunB(i-1);
}
};
}
Cmain.c
#include "stdio.h"
void mainfu(void);
void main(void)
{
printf("In CMain\n");
mainfu();
}
seemingly unavoidable requirement to have an interlock between the C# and the
C++. By this I mean that I have to have a method in C++ that calls a method
in C#, that in turn calls back to the original method in C++. I had this
working in .NET 1.1 by using my final exe as my source of metadata, but it
does not work in 2.0, and I want a proper solution. I have implemented a
small test case, but it is not working and I do not understand why. Here is
what I am doing.
- Make a C++ file containing a function, build it.
- Build a C# file that contains a function, that calls the C++ function. It
uses the metadata from the C++ build.
- Make a new C++ file, with the same name as the old one, that contains a
function with calls the C# function. So it uses the C# metadata.
There are two problems with this approach.
1) When I try and run it, it crashes with the following error:
System.BadImageFormatException: an attempt was made to load a program with an
incorrect format. I do not understand this error, my make file and source
files are below. The call stack showed that it was in the first call from the
C# back into the C++.
2) This is a horrible way of implementing an interlock, surely there must be
a better way of doing it, or a way of eliminating it? I require it because I
have a large volume of legacy code written in C++, and a GUI for it written
in C#, both of which I want to retain. The C++ can call the Get Input
function in C#, which can call back to application code in the C++. But the
application code can in turn call a separate Get Input process in the C#
again. It can go to a maximum depth of 5 or 6 levels at most.
I would appreciate any help that anyone can offer. Thanks.
Here is my make.bat file:
del *.obj
del *.netmodule
rem First, build the one way cpp.
copy cppfu.one cppfu.cpp
cl /LN /clrldsyntax cppfu.cpp
pause
al cppfu.netmodule /platform:x86 /target:lib /out:cppfu.dll
rem Next build the csc.
csc /t:module /r:cppfu.dll csuse.cs
pause
rem Next build the replacement cpp that calls back.
copy cppfu.bot cppfu.cpp
cl /LN /clrldsyntax cppfu.cpp
pause
al cppfu.netmodule /platform:x86 /target:lib /out:cppfu.dll
rem Finally, link it all together.
pause
cl /LN /clrldsyntax macpp.cpp
cl cmain.c macpp.obj /link /nodefaultlib:libcmt
Here is the source code:
Cppfu.one
#include "stdio.h"
namespace CPPFu
{
public __gc class CPPClass{ // ref was __gc.
public: static void FuA(int i)
{
printf("In CPP A %d\n",i);
}
};
}
Csuse.cs
using System;
using CPPFu;
namespace NSinCS
{
public class CSFun
{
public static void CSFunB(int i)
{
Console.WriteLine("In FuB "+i.ToString());
if(i>0) CPPFu.CPPClass.FuA(i-1);
}
}
}
Cppfu.bot
#include "stdio.h"
#using <CSUse.netmodule>
namespace CPPFu
{
public __gc class CPPClass{ // ref was __gc.
public: static void FuA(int i)
{
printf("In CPP A %d\n",i);
if(i>0) NSinCS::CSFun::CSFunB(i-1);
}
};
}
Cmain.c
#include "stdio.h"
void mainfu(void);
void main(void)
{
printf("In CMain\n");
mainfu();
}