I was gaven a C++ dll file, a lib
file and a he开发者_C百科ader file. I need to call them from my C# application.
header file looks like this:
class Clog ;
class EXPORT_MACRO NB_DPSM
{
private:
string sFileNameToAnalyze ;
Clog *pLog ;
void write2log(string text) ;
public:
NB_DPSM(void);
~NB_DPSM(void);
void setFileNameToAnalyze(string FileNameToAnalyze) ;
int WriteGenbenchData(string& message) ;
};
In my C# code, I have those code:
internal ReturnStatus correctDataDLL(string rawDataFileName)
{
if (rawDataFileName == null || rawDataFileName.Length <= 0)
{
return ReturnStatus.Return_CannotFindFile;
}
else
{
setFileNameToAnalyze(rawDataFileName);
}
string msg = "";
int returnVal = WriteGenbenchData(ref msg);
return ReturnStatus.Return_Success;
}
[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")]
public static extern void setFileNameToAnalyze(string fileName);
[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")]
public static extern int WriteGenbenchData(ref string message);
I got EntryPointNotFoundException
at the setFileNameToAnalyze(rawDataFileName);
statement.
Few questions:
do I need to add that
lib
file into somewhere of my C# project? how?do I need to add the header file into my C# project? how? (no compile error for now)
I would like to remove those
"..\\..\\thirdParty\\cogs\\"
hardcode path. how to this?how to get ride of that
EntryPointNotFoundException
?
thanks,
You don't need to include either the header file or the lib file in your C# project. These files are useless to you anyway.
The reason you are getting an EntryPointNotFound exception is that you've provided incorrect names for those entry points. When you compile a C++ project, the compiler mangles the names by adding additional information about parameters and return types. (You can use the dumpbin.exe utility to see these entry points.)
The real problem, however, is that your DLL evidentally contains a C++ class. "setFileNameToAnalyze" and "WriteGenbenchData" are instance methods of that class, not static functions. You can't call them without creating an instance of the NB_DPSM class first.
It might be possible to do that using only P/Invoke, but at this point I think it's likely more trouble than it's worth. You should create a managed C++ class library to wrap the old DLL instead.
As to part (3) of your question, just remove the paths and make sure that NB_DPSM.dll resides in the same bin directory as the result of your output files.
Place the functions outside any classes (as global functions) and in an extern "C" { ... }
block.
You don't need the header file in C#. (That's what the [DllImport]
does)
Could try make your own unmanaged C++ dll as a shim, using the provided dll have 1 method
extern "C" int GenBenchData( const string &filename, string & message ){
NB_DPSM builder;
builder.setFileNameToAnalyze(filename);
return builder.WriteGenbenchData( message );
}
in C# you declare that with
[DllImport("shim.dll", CharSet = CharSet.Auto)]
static extern int GenBenchData([MarshalAs(UnmanagedType.LPStr)]string filename, StringBuilder message);
Also beware of the calling convention. If your DLL is really C++, use a tool to visualize the exported names (like depends.exe referred in the linked article). Each C++ compiler has its own decoration scheme what makes it a bit tedious to adapt. Alternatively you can use a wrapper managed C++ assembly that links to the C++ DLL. If it is just a C interface take care of the calling convention and the type sizes (common pitfall: a long in C# is 64bit in C/C++ it is 32bit)
精彩评论