P/Invoke C# to C++ - c#

I'm trying to learn how to run C# and C++ code together using Mono on RedHat. I'm fooling around in order to learn how to get the two to interoperate together in order to be a bit more educated when I work on a larger project.
I've got a problem that I'm making a P/Invoke call from the C# to my C++ code and an exception is being thrown. Using Mono, I can get the C++ code to call the C# code no problem.
My C++ method that I want the C# to call is as follows.
extern "C"{
void Foobar(){
printf("Hooray!");
}
}
My C# code that I have uses the following P/Invoke lines.
[DllImport ("__Internal", EntryPoint="Foobar")]
static extern void Foobar();
In my C# program, I call
Foobar();
further down in a function. The exception I catch is an EntryPointNotFound exception. I'm probably overlooking something silly.
I've used http://www.mono-project.com/Embedding_Mono as instructions regarding how to do this.
Any suggestions appreciated. Thanks,
mj

Are you using embedding (that is, you build your own executable that inits the mono runtime)? In that case the possibilitites are usually two:
You have a typo
The compiler/linker removed during optimization the function from your binary
To check for either, run:
nm your_program |grep Foobar
and see if a symbol with that name is present in the executable your_program.
If you see a mangled name it means extern "C" was not applied correctly in your code.
If you're not using embedding, you need to use the dynamic library name and not __Internal in DllImport (and check for typos and the above linker optimization issue as well).

Why "__Internal"? That's for P/Invoking symbols in the Mono runtime or the program embedding the Mono runtime. How is your C++ code being compiled and linked?

I saw this exact problem, objdump -T and objdump -t differed on the host binary.
It was missing the 'D' flag, which means add a -rdynamic to the gcc linker.

Related

Debugging a failure to access libleveldb with C# on OSX

A C# project I'm interested in uses leveldb via a PInvoke 'wrapper' that works fine on both Windows and Linux but throws the following error on OSX.
src/tcmalloc.cc:331] Attempt to free invalid pointer 0x7f83cb954a00
A minimal example to reproduce the error with is
using System;
using System.Runtime.InteropServices;
namespace leveldb_test2
{
internal static class Native {
[DllImport("libleveldb", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr leveldb_options_create();
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("before");
IntPtr handle = Native.leveldb_options_create();
Console.WriteLine("after");
}
}
}
What I've tried
Manually building leveldb
Leveldb was initially installed via homebrew. Not knowing if they do anything magical, I also did a manual build which gave me the same error.
Verifying the method signature
The method signature used with DllImport seems ok, as it's identical to what's used in a wrapper project I found: leveldb-sharp (fwiw; I tried using that project, same error)
Note that original export from leveldb is
extern leveldb_options_t* leveldb_options_create();
I also created my own dll with the same signature and that worked fine. This also confirmed for me that I can correctly enforce which exact library file is being loaded to avoid it using some broken version somewhere else on my system.
Verifying library exports
I dumped the exports using nm to make sure no name mangling is going on, seems fine.
I can also access the library successfully with ctypes in Python.
Try older versions of leveldb
I tried all older versions up to 1.15 from September 2014. All give the same error.
What's next
Ideally, I'd like to be able to debug the native side. However, unlike with Visual Studio on Windows, the OSX Visual Studio Community Edition doesn't have the "Enable native code debugging" option described here. So my question is
How would I go about debugging the native side while initiated from C#?
I believe the latter part of this question is important, because as said before it works fine when initiated from Python. Any tips/hints/help are much appreciated!
PS: a bonus would be the solution to getting the wrapper to work.

Tracking disassembly of a c# program

I am trying to understand disassembly of a c# program using objdump, since I am using vsiaul c# 2008 express edition which does not display disassembly.
I am running the following command to get the output:
objdump -S ConsoleApplication4.exe
since I am not able to identify my function codein the disassembly output, I put in a dummy variable with a value of 0x1234.
public static void myfun()
{
int i;
i = 0x1234;
Console.WriteLine(i.ToString());
}
However, I am not able to find the value of 1234 anywhere in the generated file! i tried other options like -t or -T for objdump, but it says no symbol table found. Can someone please tell how to use objdump to view the disassembly of a function, or if there some other free tool?
EDIT : I am aware of MSIL disassmbler, I wanted to know the assembly language equivalent please..
Unless you have NGEN'd your application, it doesn't make sense to disassemble into assembly language since the MSIL isn't compiled into x86 code until it is jitted at runtime.
If this has to do with C# and not C++, use MSIL Disassembler. Also, if you have .Net Reflector, FileDisassembler is a great tool for this as well.
Below are the links to MSIL Disassembler's complete example step-by-step and its msdn article.
http://www.mactech.com/articles/mactech/Vol.19/19.12/NETbinaries/index.html
http://msdn.microsoft.com/en-us/library/f7dy01k1%28v=vs.71%29.aspx

How to statically-link MKL v9.x into a managed C++ DLL to calculate FFT?

I'm coding an application using C# with Visual Studio 2008. I've been reading the documentation that came with the Intel Math Library...and some forums...but couldn't get an answer.
Here is where I'm at:
Scenario:
Attempting to statically-link MKL v9.x into a managed C++ DLL to calculate FFT, using Visual Studio 2008.
Linker command:
/OUT:"C:\Projects\Acquisition Toolkit\Mainline\Builds\Debug\AcquisitionToolkit.FFT.dll" /INCREMENTAL /NOLOGO /LIBPATH:"C:\Projects\Acquisition Toolkit\Mainline\Lib\Win32" /DLL /MANIFEST /MANIFESTFILE:"Debug\Win32\AcquisitionToolkit.FFT.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /ASSEMBLYDEBUG /PDB:"c:\Projects\Acquisition Toolkit\Mainline\Builds\Debug\AcquisitionToolkit.FFT.pdb" /DYNAMICBASE /FIXED:No /NXCOMPAT /MACHINE:X86 /KEYFILE:"AcquisitionToolkit.snk" /ERRORREPORT:PROMPT mkl_c.lib mkl_ia32.lib libguide40.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Getting an unresolved external when linking:
1>FFT.obj : warning LNK4248: unresolved typeref token (0100000E) for 'DFTI_DFT_Desc_struct'; image may not run
At run-time, it crashes on the call to DftiCreateDescriptor, presumably because it didn't know the format of the descriptor struct:
// create the FFT descriptor
DFTI_DESCRIPTOR_HANDLE desc;
long val = DftiCreateDescriptor(&desc, DFTI_DOUBLE, DFTI_REAL, 1, length);
// commit the FFT descriptor
DftiCommitDescriptor(desc);
We are including the mkl_dfti.h header file.
Are there additional header files we need or additional libraries we need to link with?
Where is that descriptor struct actually defined?
I attempted to dynamically link using the mkl_c_dll.lib, but got the same unresolved external linker warning.
Is there some other linker option I need?
Please if someone could give me some kind of guidance/help. I'd REALLY appreciate it.
Thanks!!
As far as I know you can only do dynamic linking with c++/clr, i.e. /clr is incompatible with /MT[d]. You need to link to a library compiled with /MD[d] so they use the same runtime. I don't know why it fails when you do dynamic linking but your theory of incorrect descriptor sounds right
Edit: By the way, I don't know if it is an option in your situation but you can use CUDA for doing FFT (cufft) much faster on the GPU.

BadImageFormatException: PInvoke ImportDll with hdf5dll.dll

Ok, I have the HDF5 library downloaded from the official site, and I have a few DLLs, including hdf5dll.dll, and hdf5_hldll.dll.
I have what I think to be some wrappers around the native calls, in my classes H5, H5LT, H5F, and H5T. Example from H5.cs:
namespace HDF5
{
using hid_t = System.Int32;
using herr_t = System.Int32;
using hsize_t = System.UInt64;
using size_t = System.UInt32;
// hbool_t is 0:false, +:true
using hbool_t = System.UInt32;
// htri_t is 0:false, +:true, -:failure
using htri_t = System.Int32;
public class H5
{
const CharSet StringMarshallingType = CharSet.Ansi;
const string DLLNAME = "hdf5dll.dll";
///* Functions in H5.c */
//H5_DLL herr_t H5open(void);
[DllImport(DLLNAME,
CharSet = StringMarshallingType)]
public static extern herr_t H5open();
And in Program.cs, I use H5.H5open();, but I get a BadImageFormatException. Do I need a different DLL? Does the method signature look wrong?
I'd like to, as the next step, get this in C#: http://www.hdfgroup.org/HDF5/Tutor/h5lite.html .
OS: Windows 7 64 bit
Environment: Visual Studio 2008 Professional
Update: I don't know if this will be related, and I don't remember if my environment is VS2008 SP1, but this question may hold a key to solving the mystery. I am as of now trying to repeat the scenario on 32 bit VS 2010 at home.
That happens when you're trying to run P/Invoke operations on a dll meant for x86 architecture from within an x64 process or vice versa. I'd check all of that and if they're out of sync, consider targeting the processor that HDF5 targets with your application, or checking if a processor-specific version is available.
Looking at the documentation from here, the function prototype is:
herr_t H5open(void);
And also the DLLNAME is disallowed, you must explicitly specify the dll name - no questions asked.
The proper signature is:
[DllImport("hdf5dll.dll")]public static extern herr_t H5open();
Make sure you have the type herr_t defined...
Let the runtime take care of the marshalling for you....
Also make sure, the DLL is present in the same path as where the compiled .EXE (your code) is generated.
Edit: Thanks to the OP for pointing out my blooper....
On x64 operatingsystems .net programs usually run in x64 mode.
Just set your target processor architecture to x86 and try again.
Just in Visual studio open your "Solution Configuration"-Manager and add a new target Platform.

C# DllImport return type is TCHAR?

I have a c++ function with the following signature
TCHAR *DXGetErrorDescription9(HRESULT hr);
I have
[DllImport("dxerr9.dll",EntryPoint="GetDXErrorString9")]
static public extern string GetDXErrorString9(int DXError);
How do I marshall string to TCHAR*? Thanks
After doing a little digging, it turns out that the directx error routines are not shipped as dlls, they're shipped as libs that you statically link into your executable. I should have figured this based on the size of dxerr9.lib (it's 5M, way larger than any of the other stub libs).
So to get this to work I did the following:
Make a "wrapper" native dll that wraps all the error handling lib functions. Since there are only 3 (DXGetErrorDescription, DXGetERrorString and DXTrace) this isn't that big a deal.
Have .NET call the wrapper functions.
You can do this in visual studio by creating a Win32 project (change application settings so that it's a dll and so that it exports symbols). I called min "DirectXErrWrapper".
Inside the wrapper project add a passthrough for the DXGetErrorDescription. I called mine DXGetErrDescPassThrough():
extern "C" {
DIRECTXERRWRAPPER_API TCHAR * DXGetErrDescPassThrough(HRESULT hr)
{
return (TCHAR *)DXGetErrorDescription(hr);
}
}
The extern "C" block is important (has to do with demangling the C++ names). This project will need to #include "dxerr.h" and statically link dxerr.lib so you'll have to add the directx sdk include dir to your include path and the directx sdk lib dir to your lib path.
Then have your managed code import the call from your wrapper dll:
[DllImport("DirectXErrWrapper.dll", CharSet=CharSet.Unicode)]
static public extern string DXGetErrDescPassThrough(int DXError);
In 2005 native projects use unicode by default so the DllImport needed to specify unicode. Lastly, call it from managed code via:
Debug.WriteLine("DXGettErrDescPassThrough=" + DXGetErrDescPassThrough(0));
In this case the call prints "The function completed successfully" to the debug device since 0 is success.
(previous post follows)
That looks like one of the DirectX functions (C++ not C# AFAIK). I'm pretty sure it ships with unicode and ansi versions.
TCHAR will map to unicode when compiled on unicode (the T is a mnemonic for type; unicode on unicode, multibyte characterset on mbcs, ansi otherwise).
You can usually use CharSet=CharSet.Auto but if that causes compatability problems (e.g., you've gotta use ansi strings because of some struct that you've already ported requires it) you can use whichever is consistent with your project (either Charset.Unicode if you're all unicode or Charset.Ansi) you should have no problem marshaling it into a C# string. You may need to decorate it as [OUT] though the return value may be OUT implicitly.
I too wish DirectX shipped w/ TLBs following the standard [out, retval] convention!

Categories