Calling a dll using pinvoke from c# is much slower than calling it in C++

B

Beorne

I have a propertary library dll (used to drive a device) that I call
from my C# code.
Calling the functions from C++ is really faster than calling them in C+
+. From C++ the call is almost instantaneous, from C# is about 1.5
seconds long.

For example, this command powers a device based on an interface switch
and returns a message in Ack_Msg that is len long. Besides returns an
error code.

The C++ function header is:
long __cdecl Grid_On_Off(BOOL *GridsOnOff, char Ack_Msg[], long len);

in C++ is called as:
void CCanCtrlDlg::OnGridOnOff(NMHDR* pNMHDR, LRESULT* pResult)
{
char cAcknowledge_Msg[300];
BOOL bGrids = m_Grids.GetPos();
long lError = C_Grid_On_Off(&bGrids, cAcknowledge_Msg, LG_MAX_STR);
}

I declare it in C# as
[DllImport("device_library", CharSet = CharSet.Ansi, CallingConvention
= CallingConvention.Cdecl)]
public static extern int Grid_On_Off(ref bool GridsOnOff,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder Ack_Msg, int len);

I call it in C# from inside a button in the following way:
private void checkBoxGridOnOff_CheckedChanged(object sender, EventArgs
e)
{
StringBuilder ack_Msg = new StringBuilder(300);
bool tf = checkBoxOnOff.Checked;
int error = Grid_On_Off(ref tf, ack_Msg, 300)
}

What is the reason calling from C# is much slower? Can I do something
about it?
Thank you very much.
 
N

Nicholas Paldino [.NET/C# MVP]

Beorne,

Not really. P/Invoke has to load the dll (a call to LoadLibrary), then
get the procedure address (GetProcAddress), and then marshal all the
parameters from managed memory to unmanaged memory, construct the stack, and
then make the call.

It then has take the results off the stack and marshal them back to
managed code.

Needless to say, there is always going to be some overhead when making
calls through P/Invoke.

The overhead is not there in C++ because C++ doesn't have to call
LoadLibrary, doesn't have to marshal parameters, and doesn't have to set up
the stack for calling conventions and the like (not in the way the runtime
has to do it, at least).
 
W

Willy Denoyette [MVP]

Beorne said:
I have a propertary library dll (used to drive a device) that I call
from my C# code.
Calling the functions from C++ is really faster than calling them in C+
+. From C++ the call is almost instantaneous, from C# is about 1.5
seconds long.

How did you measure this? I can't believe this takes 1.5 seconds unless you
are loading the library (device_library) over a network connection, or you
are running this on an (over)loaded system and too slow system.
Note that the initial call is somewhat slower than succeeding calls, this
because the library has to be loaded first, but this can't hardly take 1.5
seconds. Succeeding calls only take a hit because of the char[] marshaling,
but again this is a matter of fractions_of µseconds.


Willy.
 
B

Beorne

You are right, the slow response was due to a timer set too tight,
pinvoke marshalling is in general fast enough.

Thanks!


I have a propertary library dll (used to drive a device) that I call
from my C# code.
Calling the functions from C++ is really faster than calling them in C+
+. From C++ the call is almost instantaneous, from C# is about 1.5
seconds long.

How did you measure this? I can't believe this takes 1.5 seconds unless you
are loading the library (device_library) over a network connection, or you
are running this on an (over)loaded system and too slow system.
Note that the initial call is somewhat slower than succeeding calls, this
because the library has to be loaded first, but this can't hardly take 1.5
seconds. Succeeding calls only take a hit because of the char[] marshaling,
but again this is a matter of fractions_of µseconds.

Willy.
 

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