Loading native code dll using vc++ .net 2.0 managed code

A

antarikshv

I am loading a native dll, i.e. a dll created using native code. My
development environment is VC++ .Net 2.0, managed code.

The code is as follows,
The function signature in the dll is:
int CalculateKey(BYTE *seed, int seedLength, BYTE *key, int
keyLength);

the delegate declaration in my code is:

delegate int CalculateKey(int * seed, int seedLength,int * key, int
keyLength);

the code for loading of the dll and using its function:

OpenFileDialog ^ of = gcnew OpenFileDialog();
of->ShowDialog();

IntPtr hExe = LoadLibrary(of->FileName);
if (hExe.ToInt32() == 0)
{
MessageBox::Show("Cannot open " + of->FileName);
}

GCHandle ^ gch = GCHandle::Alloc(of->FileName,GCHandleType::pinned); //
convert object to handle
IntPtr hProc = GetProcAddress(hExe,"CalculateKey");
if(hProc.ToInt32() == 0)
{
MessageBox::Show("Not Found");
}

CalculateKey ^ ObjCalcFunc = (CalculateKey ^)
Marshal::GetDelegateForFunctionPointer(hExe,CalculateKey::typeid);

array<char> ^ uSeed = gcnew array<char>{1,2,3,4};
array<char> ^ uKey = gcnew array<char>(4);
pin_ptr<char> pinptrp = &uSeed[0];
pin_ptr<char> pinptrp1 = &uKey[0];
int * ppp = reinterpret_cast<int *>(pinptrp);
int * ppp1 = reinterpret_cast<int *>(pinptrp1);
ObjCalcFunc(ppp,uSeed->Length,ppp1,uKey->Length);

With the above code i am facing the exception when the ObjCalcFunc is
called as

"An unhandled exception of type 'System.AccessViolationException'
occurred in tesbed.exe

Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt."

Now i have searched various sites for finding a solution to this, but
haven't succeeded yet. Please let me know the solution.
Thanks in advance.
 
P

Pavel Minaev

I am loading a native dll, i.e. a dll created using native code. My
development environment is VC++ .Net 2.0, managed code.

Firstly, why are you doing it that way? Since you're already using C++/
CLI, you have full access to native API functions anyway - so why not
just use LoadLibrary/GetProcAddress to get a proper native function
pointer, and then invoke that directly? Why wrap it into the delegate?
The code is as follows,
The function signature in the dll is:
int CalculateKey(BYTE *seed, int seedLength, BYTE *key, int
keyLength);

the delegate declaration in my code is:

delegate int CalculateKey(int * seed, int seedLength,int * key, int
keyLength);

Why does the signature not match? Why the pointers are int*, not
unsigned char*?

In addition, what is the calling convention of the native function? If
it is the default __cdecl, then you're missing this attribute on your
delegate declaration:

[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
the code for loading of the dll and using its function:

OpenFileDialog ^ of = gcnew OpenFileDialog();
of->ShowDialog();

IntPtr hExe = LoadLibrary(of->FileName);
if (hExe.ToInt32() == 0)

You can compare to IntPtr::Zero
{
   MessageBox::Show("Cannot open " + of->FileName);

}

GCHandle ^ gch = GCHandle::Alloc(of->FileName,GCHandleType::pinned); //
convert object to handle
IntPtr hProc = GetProcAddress(hExe,"CalculateKey");
if(hProc.ToInt32() == 0)
{
   MessageBox::Show("Not Found");

}

CalculateKey ^ ObjCalcFunc = (CalculateKey ^)
Marshal::GetDelegateForFunctionPointer(hExe,CalculateKey::typeid);

array<char> ^ uSeed = gcnew array<char>{1,2,3,4};
array<char> ^ uKey = gcnew array<char>(4);
pin_ptr<char> pinptrp = &uSeed[0];
pin_ptr<char> pinptrp1 = &uKey[0];
int * ppp = reinterpret_cast<int *>(pinptrp);
int * ppp1 = reinterpret_cast<int *>(pinptrp1);
                                 ObjCalcFunc(ppp,uSeed->Length,ppp1,uKey->Length);

With the above code i am facing the exception when the ObjCalcFunc is
called as

"An unhandled exception of type 'System.AccessViolationException'
occurred in tesbed.exe
 
A

antarikshv

I wanted to go ahead with only managed code as far as possible. i had
previously used the LoadLibrary/GetProcAddress
functions, but the end result was the same exception.
  [UnmanagedFunctionPointer(CallingConvention::Cdecl)]

with the delegate attribute, i shall try.
 
A

antarikshv

i tried with the changes you mentioned, but still i am encountering
the exception.
the changes i implemented:
1. checked with LoadLibrary/GetProcAddress
2. char *

but it didnt go through. so came back to wrapping with delegate and
used
1. attribute to delegate.

But still the exception
"An unhandled exception of type 'System.AccessViolationException'
occurred in tesbed.exe
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt."

is coming. Were the suggestion you provided for removing this
exception?
Any reason as to why this exception is occuring?
 
P

Pavel Minaev

i tried with the changes you mentioned, but still i am encountering
the exception.
the changes i implemented:
1. checked with LoadLibrary/GetProcAddress
2. char *

but it didnt go through. so came back to wrapping with delegate and
used
1. attribute to delegate.

But still the exception
"An unhandled exception of type 'System.AccessViolationException'
occurred in tesbed.exe
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt."

is coming. Were the suggestion you provided for removing this
exception?
Any reason as to why this exception is occuring?

The exception obviously indicates that something is reading or writing
an invalid pointer. Since your input values all look correct, this
implies that the native function gets them wrong somehow - for
example, because it reads the arguments incorrectly due to a calling
convention mismatch.

Do you get the same error when you call the LoadLibrary/GetProcAddress
and the returned native function pointer directly (i.e. not via P/
Invoke)?
 
A

antarikshv

Dear all,
i found the mistake in the code
I was using hExe instead of hProc in
Marshal::GetDelegateForFunctionPointer

OpenFileDialog ^ of = gcnew OpenFileDialog();
of->ShowDialog();
IntPtr hExe = LoadLibrary(of->FileName);
if (hExe.ToInt32() == 0)
{
MessageBox::Show("Cannot open " + of->FileName);
}


GCHandle ^ gch = GCHandle::Alloc(of->FileName,GCHandleType::pinned); //
convert object to handle
IntPtr hProc = GetProcAddress(hExe,"CalculateKey");
if(hProc.ToInt32() == 0)
{
MessageBox::Show("Not Found");
}
CalculateKey ^ ObjCalcFunc = (CalculateKey ^)
Marshal::GetDelegateForFunctionPointer(hProc ,CalculateKey::typeid);

array<char> ^ uSeed = gcnew array<char>{1,2,3,4};
array<char> ^ uKey = gcnew array<char>(4);
pin_ptr<char> pinptrp = &uSeed[0];
pin_ptr<char> pinptrp1 = &uKey[0];
int * ppp = reinterpret_cast<int *>(pinptrp);
int * ppp1 = reinterpret_cast<int *>(pinptrp1);
ObjCalcFunc(ppp,uSeed->Length,ppp1,uKey->Length);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top