|
How are you currently calling PcDllInit() from your c# code?
What are you passing as the char[] parameter - a string?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: How are you currently calling PcDllInit() from your c# code?
What are you passing as the char[] parameter - a string?
Below is my Main method that makes the call to PcDllInit.
static void Main(string[] args)
{
char[] pwd = new char[64];
pwd = "xxxxxx".ToCharArray();
Int32 AutoDeleteFlag = 1;
Int32 LogFlag = 1;
cbd = new CallBackDelegate(PcDllCbMsg);
try
{
PcDllInit(pwd, AutoDeleteFlag, LogFlag, cbd);
}
Thanks
|
|
|
|
|
Cool, thanks.
That's definitely a problem since the C++ side is expecting an
array of 64 bytes passed, but C# is passing 128 bytes.
I've got a couple fellow MVPs firing solutions at me here...
I'll be back...
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
So from what i've been reading it looks like I need to use a String on the C# side and marshal them to be a char[] with the given size. I implemented that following an example from the msdn http://msdn.microsoft.com/en-us/library/aa288468.aspx#pinvoke_example2[^]. I followed it but when I compile I get the following error.
Error 1 Error emitting 'System.Runtime.InteropServices.MarshalAsAttribute' attribute -- 'Specified unmanaged type is only valid on fields.' C:\views\QaView\In-Sight_FW_QA\Qa\Apps\QaUtils.NET\ProductConfigAPI\ProdConfigAPI.cs 43 36 ProductConfigAPI
Here Is the what the code looks like now after implementing the marshaling.
The Callback Delegate:
delegate void CallBackDelegate(PC_MSG_TYPE PcMsgType,
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] String MsgTgt,
int Verbosity,
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=512)] String Msg);
DllImport:
[DllImport("ProdConfigAppDll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern Int32 PcDllInit([MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
String PcDllPwd,
Int32 AutoDeleteFlag,
Int32 LogFlag,
CallBackDelegate PcMsgCb);
And the call to PcDllInit:
Int32 AutoDeleteFlag = 1;
Int32 LogFlag = 1;
String password = "xxxxxx";
cbd = new CallBackDelegate(PcDllCbMsg);
try
{
PcDllInit(password, AutoDeleteFlag, LogFlag, cbd);
}
Any Ideas about this compile error, or if this is even a solution to my problem? It looks to me like I've followed the example given in the msdn.
Thanks
|
|
|
|
|
MarshalAs(UnmanagedType.ByValTStr can only be used on members of a structure.
Ok, ignoring the callback stuff at the moment, I tried this:
[DllImport("DLL.dll", CallingConvention = CallingConvention.Cdecl)]
static extern Int32 PcDllInit([MarshalAs(UnmanagedType.LPStr)] StringBuilder PcDllPwd,
Int32 AutoDeleteFlag,
Int32 LogFlag);
...
String password = "xxxxx";
PcDllInit(password, AutoDeleteFlag, LogFlag);
That fixes the stack corruption calling the native code.
The delegate strings should be marshaled as UnmanagedType.LPStr as well
I believe. If that doesn't work, try using StringBuilders instead of Strings
in the elegate params.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Awesome, thanks that seems to have fixed it. I did have to convert all String's to the StringBuilder class too. However now there's a new issue when the callback delegate returns. I'm getting an AccessViolationException. Reading up on this exception the msdn says this is thrown when a pointer has a bad value. Any idea's?
And thanks again for helping me through that other issue.
|
|
|
|
|
jamesmurphy78 wrote: I'm getting an AccessViolationException
Yeah I was just going to send you what should be the final fix.
Delegates should be called using __stdcall...
On the C++ side:
DllImpExp int PcDllInit(const char PcDllPwd[64], int AutoDeleteFlag,
int LogFlag,
void (<code>__stdcall</code> PcMsgCb)(PC_MSG_TYPE PcMsgType,
const char MsgTgt[MAX_PCDLL_STRING_LEN],
int Verbosity,
const char Msg[512]));
I tested with Strings, not StringBuilders and it seemed to work well.
You can get rid of the "SizeConst =" on the C# side marshaling, since the size can't
be enforced anyway (only array pointers are being passed). Having them there,
however, does document the max string sizes I guess.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Fantastic Thank you so much for helping me through this. Everything works. I added __stdcall to the dll side and changed everything back to String on the C# side and everything worked out. Thanks again and have a good day!
|
|
|
|
|
Cool! Once I realized arrays aren't EVER passed by value
(pointed out by a fellow MVP) it was fairly straight forward.
Apparently I need to dust off my "C Programming for Idiots" book
You have a great day as well.
Cheers,
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I need to override GetHashCode based on two Int32s.
Obviously, I can't get unique hash codes as it has to return one Int32.
I'm doing this at the moment, is there a better way to do it?
(m_Lower and m_Upper are both Int32)
public override int GetHashCode()
{
return (((Int64)m_Upper << 32) + m_Lower).GetHashCode();
}
I couldn't find any documentation on how Int64 implements it.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
The only strict requirement for the GetHashCode method is that it should always return the same hash code for a given value. So, this is a valid implementation of the method:
public override int GetHashCode() {
return 0;
}
However, that gives bad performance when you use the hash code for example in a dictionary. For good performance, the hash codes should be evenly distributed over the Int32 range of values.
This is how the implementation looks for the Int32 type:
public override int GetHashCode() {
return this;
}
This is how the implementation looks for the Int64 type:
public override int GetHashCode() {
return ((int)this) ^ ((int)(this >> 0x20));
}
As you see, it just throws away the top 12 bits. If you want to use all the bits in the hash code, you can just do an xor of the upper and lower value:
public override int GetHashCode() {
return m_Upper ^ m_Lower;
}
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Guffa wrote: throws away the top 12 bits
Actually, it's just splitting it into 2 ints and xoring them - 0x20 (Hex!)
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|
|
Yes, you are right. Why didn't I think of that, that is what I would expect it to do...
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Which is the elemental code for searching in a datagridview column?. How to give the focus at the row with the value found?
|
|
|
|
|
Not sure what you're trying to do but you don't need to search into Columns, you can simply search in Rows:
DataGridView dgv = new DataGridView();
DataGridViewRow dgvr = new DataGridViewRow();
dgvr.Cells[0].Value = "Hello!";
dgv.Rows[dgv.Rows.IndexOf(dgvr)].Selected = true;
While (true) { Human.isLearnable = true; }
|
|
|
|
|
You can do that with sql procedures, after trigger it in a c# event
nelsonpaixao@yahoo.com.br
trying to help & get help
|
|
|
|
|
|
Hi guys,
Need some help please. I have a scan feature in my form and on form_load I am trying to fire the btnScan.performclick() event. It works but my form doesn't load until scanner times out or then I scan. I want the form to load and the picturebox to show no image while the scanner is waiting for an image.
I hope I am making sense.
Sameer
Sameer
|
|
|
|
|
Have a timer that gets started in the form load event, and then do the btnScan.PerformClick() in the timer's event handler.
-----
In the land of the blind, the one eyed man is king.
|
|
|
|
|
Thank you for your suggestion, it worked...
S
Sameer
|
|
|
|
|
I think you need Threading[^]
While (true) { Human.isLearnable = true; }
|
|
|
|
|
can you please give me an example
Thanks
Sameer
|
|
|
|
|
Sure[^]
While (true) { Human.isLearnable = true; }
|
|
|
|
|
For simplicity - use the BackgroundWorker component.
DaveBTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)Visual Basic is not used by normal people so we're not covering it here. (Uncyclopedia)
|
|
|
|