DLLimport using and Error - c#

I have a c++ native dll file and I should call some functions from Dll by c#
the c++ function that I should call is
extern NCSError NCS_CALL NCSOpenFileViewA(const char *szUrlPath, NCSFileView **ppNCSFileView,NCSReadStatus (*pRefreshCallback)(NCSFileView *pNCSFileView));
NCSFileView object is
typedef struct NCSFileViewStruct NCSFileView;
and working example c++ code is
NCS::CApplication App
NCSCompressClient *pClient;
char *szInputFilename = "C:\\testdata\\RGB_8bit.ecw";
NCSFileView *pNCSFileView;
NCSFileInfo *pNCSFileInfo;
NCSFileMetaData *pNCSFileMeta;
NCSError eError;
NCSInit();
eError = NCSOpenFileViewA(szInputFilename, &pNCSFileView, NULL);
if (eError != NCS_SUCCESS) {
ReportError("Could not open view for file:%s, Error = %s",
szInputFilename, NCSGetErrorText(eError));
exit(1);
}`
I made a c# code like this
[DllImport("C:\\NCSEcw.dll",CallingConvention=CallingConvention.Cdecl)]
public static extern IntPtr NCSOpenFileViewA ([MarshalAs(UnmanagedType.LPStr)] string path,
IntPtr a,
IntPtr c);
but i get en error like this
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
so, can you help me to write wrapper?

Related

Equivalent of C++ "this" pointer in C#

I'm trying to translate a successfully working C++ program to C# and I'm currently stuck at initializing the audio output device. I would like to know the equivalent of 'this' pointer in C#.
Below is the working C++ code:
DWORD WINAPI SCFStartOutSound(SCFHANDLE sohOwnerHandle, SCFHANDLE *pscfHandle, SCFEventOutSoundCallback lpfnEventCallback, BSTR FileName);
CCComBSTR FileName = "Out_DxSpeaker.dll";
HANDLE OutSoundHandle = NULL;
SCFStartOutSound(this, &OutSoundHandle, OnSCFEventOutSoundCallback, FileName);
Class:
CTestAppDlg::CTestAppDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestAppDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
Typedef:
typedef HANDLE SCFHANDLE;
Result: The audio output device is properly initialized
Initialized output device
Now here is the my C# translated code:
[DllImport(DllFileName.dll)]
unsafe public static extern uint SCFStartOutSound(IntPtr OwnerHandle,IntPtr* soundoutHandle, SCFEventOutSoundCallback EventCallback, [MarshalAs(UnmanagedType.BStr)] string fileName);
unsafe
{
IntPtr soundOutPtr;
uint res = SCFStartOutSound(this.Handle, &soundOutPtr, onSoundOutEventCallback,"Out_DxSpeaker.dll");
MessageBox.Show(res.ToString());
}
This code results to a System.AccessViolationException.
I know that 'this' in C++ is a pointer that holds the memory address of the current object while 'this' in C# refers to the current instance of the class .

access violation exception while calling the c++ code from c#

I'm trying to use phash library using this wrapper https://github.com/ludoviclefevre/phash-integration-in-csharp
c++ header:
int ph_dct_imagehash(const char* file,ulong64 &hash)
c# dll import:
DllImport(#"pHash.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ph_dct_imagehash(string file, ref ulong hash);
test code:
ulong hash = 0;
foreach (var file in files)
{
ph_dct_imagehash(file, ref hash);
dictionary.Add(file, hash);
}
It works perfectly for few picture, but when ther's about 200-300 pictures i got Accesviolation exception
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
My first lead is garbage collector but i'm confused.. should i use intpr instead of string and hash parameters? I tried changing ref parameter to out but it doesn't matter..

Sending a C# string as an argument to a unmanaged C++ DLL function

I want to send my C# string to a C++ DLL function. I have succeeded, both with StringBuilder:
[C#]
public static extern int installHook(StringBuilder directory);
StringBuilder myText = new StringBuilder(512);
myfunc(myText);
[C++]
int OPENGLHOOK_API myfunc(char* directory)
{
::MessageBoxA(NULL,directory,"test123",0);
}
and with a simple string & wchar:
[C#]
public static extern int installHook(string directory);
myfunc("myText");
[C++]
int OPENGLHOOK_API installHook(wchar* directory)
{
wstring s = directory;
const wchar_t* wstr = s.c_str();
size_t wlen = wcslen(wstr) + 1;
char newchar[100];
size_t convertedChars = 0;
wcstombs_s(&convertedChars, newchar, wlen, wstr, _TRUNCATE);
::MessageBoxA(NULL,newchar,"test123",0);
}
as it was mentioned in other thread on StackOverflow. The problem is that everytime I do this, I get an error because the function signatures are not the same:
Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\Users\Dave\Documents\Visual Studio 2010\Projects\OpenGLInjector\Loader\bin\Release\Loader.vshost.exe'.
Additional Information: A call to PInvoke function 'Loader!Loader.Form1::myfunc' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
Any idea how I can fix my problem/what to do from here?
I believe the problem is the default calling convention between the two languages. C# is __stdcall and c++ is __cdecl, I believe. Try explicitly stating __stdcall on your C++ method signatures and see if that doesn't resolve the error.
C++:
int OPENGLHOOK_API __stdcall installHook(wchar* directory)
C#:
[DllImport( "yourdll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode )]
static extern int installHook(string directory);
You need to explicitly describe the unmanaged calling convention for 32bit, and in addition, you will need to explicitly describe the unmanaged string type- ASCII, UTF16, etc.

P/Invoke code works on WinXP, exception on Win2k8

I'm attempting to access a function in a DLL in C# and C++.
C++ is working fine, as is C# on WinXP. However I'm getting the following error when attempting to access the function on a Win2k8 system:
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory
is corrupt.
at Router.GetAddress()
The declaration in C# is:
[DllImport("Constants.dll")]
static extern String GetAddress();
Usage in C# (at the moment) is just outputting it:
Console.WriteLine(GetAddress());
And the contents of the DLL's function are just:
const static WCHAR* szAddress= L"net.tcp://localhost:4502/TestAddress";
extern "C" __declspec(dllexport) const WCHAR* GetAddress()
{
return szAddress;
}
I really didn't think there was anything controversial here. The only thing I can think of is the const return from GetAddress, but I'm not sure how to apply the corresponding keyword to C# as I'm not as familiar with that language yet.
Any suggestions would be greatly appreciated.
I ended up fixing this problem using the details in http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/4e387bb3-6b99-4b9d-91bb-9ec00c47e3a4.
I changed the declaration to:
[DllImport("Constants.dll", CharSet = CharSet.Unicode)]
static extern int GetAddress(StringBuilder strAddress);
The usage therefore became:
StringBuilder sb = new StringBuilder(1000000); // Arbitrary length for the time being
GetAddress(sb);
Console.WriteLine(sb.ToString());
And the DLL was changed to:
const static WCHAR* szAddress = L"net.tcp://localhost:4502/TestAddress";
extern "C" __declspec(dllexport) int GetAddress(WCHAR* strAddress)
{
wcscpy(strAddress, szAddress);
return 0;
}

Passing a string variable as a ref between a c# dll and c++ dll

I have a c# dll and a c++ dll . I need to pass a string variable as reference from c# to c++ . My c++ dll will fill the variable with data and I will be using it in C# how can I do this. I tried using ref. But my c# dll throwed exception . "Attempted to read or write protected memory. ... This is often an indication that other memory is corrupt". Any idea on how this can be done
As a general rule you use StringBuilder for reference or return values and string for strings you don't want/need to change in the DLL.
StringBuilder corresponds to LPTSTR and string corresponds to LPCTSTR
C# function import:
[DllImport("MyDll.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static void GetMyInfo(StringBuilder myName, out int myAge);
C++ code:
__declspec(dllexport) void GetMyInfo(LPTSTR myName, int *age)
{
*age = 29;
_tcscpy(name, _T("Brian"));
}
C# code to call the function:
StringBuilder name = new StringBuilder(512);
int age;
GetMyInfo(name, out age);
Pass a fixed size StringBuilder from C# to C++.

Categories

Resources