|
You are correct about the struct - I missed the union
[StructLayout(LayoutKind.Explict)]
private struct LINEINITIALIZEEXPARAMS
{
[FieldOffset(0)]
public uint dwTotalSize;
[FieldOffset(4)]
public uint dwNeededSize;
[FieldOffset(8)]
public uint dwUsedSize;
[FieldOffset(12)]
public IntPtr hEvent;
public IntPtr hCompletionPort;
[FieldOffset(12)]
public uint dwCompletionKey;
}
Are you sure you have the dll installed as it seems windows can't find it? If it's on your system, try using an absolute path.
|
|
|
|
|
Excellent thread, except:
DaveyM69 wrote: [FieldOffset(12)]
public uint dwCompletionKey;
IMO it is either 16 (Win32) or 20 (Win64).
|
|
|
|
|
I'm never 100% sure about unions not being a C guy. I believe that at byte 12 will be either hEvent OR dwCompletionKey .
The way I understand it is that if the handles aren't used then the size of the struct will be 16 bytes, if the handles aren't are used, then the size will be 20 bytes if Win32 or 28 if Win64. The location of dwCompletionKey /hEvent will always be 12 and only the size of the struct will be different.
Please correct me if I'm wrong!
|
|
|
|
|
Hi Dave,
This is the original definition from MSDN:
typedef struct lineinitializeexparams_tag {
DWORD dwTotalSize;
DWORD dwNeededSize;
DWORD dwUsedSize;
DWORD dwOptions;
union {
HANDLE hEvent;
HANDLE hCompletionPort;
} Handles;
DWORD dwCompletionKey;
} LINEINITIALIZEEXPARAMS, *LPLINEINITIALIZEEXPARAMS;
in C/C++ every struct member that is not inside a union block will be layed out sequentially; and everything inside a union block will share the same memory (and needs the size of the largest item), so here hEvent and hCompletionPort are overlapping, however dwCompletionKey (not being part of the union) must be at the next suitable address following the union, hence at start of union item plus 4 ot 8 depending on pointer sizes.
BTW: there seems to be a dwOptions member too, which hasn't been mentioned before!
|
|
|
|
|
Hmm... intersting. The only time I've written code requiring it was for MMTIME[^] which I have like this
[StructLayout(LayoutKind.Explicit)]
internal struct MMTIME
{
[FieldOffset(0)]
public uint wType;
[FieldOffset(4)]
public uint ms;
[FieldOffset(4)]
public uint sample;
[FieldOffset(4)]
public uint cb;
[FieldOffset(4)]
public uint ticks;
[FieldOffset(4)]
public byte hour;
[FieldOffset(5)]
public byte min;
[FieldOffset(6)]
public byte sec;
[FieldOffset(7)]
public byte frame;
[FieldOffset(8)]
public byte fps;
[FieldOffset(9)]
private byte dummy;
[FieldOffset(10)]
private ushort pad;
[FieldOffset(4)]
public uint songptrpos;
}
Luc Pattyn wrote: there seems to be a dwOptions member too, which hasn't been mentioned before!
I had that in the original reply[^] but missed it when I looked at the union
|
|
|
|
|
That looks OK; there is one union, all its members are starting at the same offset (4), and nothing is following the union (both inner structs are inside the union, the union is the last member of the outer struct).
|
|
|
|
|
|
According to P/Invoke.net, lineInitializeEx is in coredll.dll NOT cellcore.dll
|
|
|
|
|
Yes, you are right. I had success to execute it now. Thank you very much!
There is some white cloud floating on the blue sky. That's the landscape I like.
|
|
|
|
|
Following the discussion I had with Luc, I've done some investigation into the way uinions work, and he is correct, the parameters inside the union block start at the same place in memory - in otherwords, the struct will contain one of the handles but not both so the best way to declare it is:
[StructLayout(LayoutKind.Sequential)]
private struct LINEINITIALIZEEXPARAMS
{
public uint dwTotalSize;
public uint dwNeededSize;
public uint dwUsedSize;
public uint dwOptions;
public IntPtr handle;
public uint dwCompletionKey;
}
|
|
|
|
|
I'm glad to see your answer. But now I meet a new problem, that I can't get HINSTANCE. I had find some ways in MSDN. But no available way I found. Could you be kind to help me again? Thank you!
There is some white cloud floating on the blue sky. That's the landscape I like.
modified on Monday, September 13, 2010 2:03 AM
|
|
|
|
|
MSDN says: "Instance handle of the client application or DLL. The application or DLL can pass NULL for this parameter, in which case TAPI uses the module handle of the root executable of the process (for purposes of identifying call handoff targets and media mode priorities).
The clue is "can pass NULL", which in the case of PInvoke handles is IntPtr.Zero . That should work.
If not, have a look at the Process.Handle[^] property - perhaps this will work?
IntPtr hInstance = System.Diagnostics.Process.GetCurrentProcess().Handle;
and pass hInstance as the parameter..., I prefer IntPtr.Zero though!
|
|
|
|
|
I had tested the code above. I feel sorry that it can't work. Because I am developing application for Windows Mobile. The property System.Diagnostics.Process.GetCurrentProcess().Handle can't be get in Mobile. I had try to give hInstance with the value of new IntPtr(GetModuleHandle(new IntPtr(0)).ToInt32()) . But when I call lineInitializeEx with it, the return value is an error code. That tell me the value of handle is invalid(0x80000035). Base of all, I think I can't call lineInitializeEx with C# at all. Isn't it?
There is some white cloud floating on the blue sky. That's the landscape I like.
|
|
|
|
|
Have you tried with IntPtr.Zero or new IntPtr(0)
What is the error code? It should be one of these:
public const uint LINEERR_NOERROR = 0x00000000;
public const uint LINEERR_INVALAPPNAME = 0x80000015;
public const uint LINEERR_INIFILECORRUPT = 0x8000000E;
public const uint LINEERR_INVALPARAM = 0x80000032;
public const uint LINEERR_INVALPOINTER = 0x80000035;
public const uint LINEERR_NOMEM = 0x80000044;
public const uint LINEERR_OPERATIONFAILED = 0x80000048;
public const uint LINEERR_REINIT = 0x80000052;
If the version of WinMob you're targetting supports TAPI then it will work once you get it just right!
Maybe post your lineInitializeEx and LINEINITIALIZEEXPARAMS ...
|
|
|
|
|
I had try to use the value of IntPtr.Zero and new IntPtr(0) before. The return value is error too. In all cases, the error code returned is still public const uint LINEERR_INVALPOINTER = 0x80000035; . I am sure my Window Mobile support TAPI. I had developed a TAPI application with C++. Thank you!
There is some white cloud floating on the blue sky. That's the landscape I like.
|
|
|
|
|
Can you post your function and struct declarations?
|
|
|
|
|
public bool OpenLine()
{
UInt32 dwDevNum = 0;
UInt32 dwApiVerSion = TAPI_CURRENT_VERSION;
LINEINITIALIZEEXPARAMS dtParams = new LINEINITIALIZEEXPARAMS();
dtParams.dwTotalSize = (UInt32)Marshal.SizeOf(dtParams);
dtParams.dwOptions = 1;
IntPtr handles = new IntPtr(0);
IntPtr hInstance = IntPtr.Zero;
unsafe
{
fixed(IntPtr *hLineApp = &m_hLineApp)
{
long lResult = lineInitializeEx(hLineApp, hInstance, new IntPtr(0), new IntPtr(0),
new IntPtr(&dwDevNum), new IntPtr(&dwApiVerSion), new IntPtr(&dtParams));
if (lResult == 0)
{
return true;
}
}
return false;
}
}
[StructLayout(LayoutKind.Sequential)]
private struct LINEINITIALIZEEXPARAMS
{
public uint dwTotalSize;
public uint dwNeededSize;
public uint dwUsedSize;
public uint dwOptions;
public IntPtr hMultiUse;
public uint dwCompletionKey;
}
[DllImport("coredll.dll", SetLastError = true)]
unsafe private static extern uint lineInitializeEx(
IntPtr *lphLineApp,
IntPtr hInstance,
IntPtr pfnCallback,
IntPtr FriendAppName,
IntPtr pNumDevs,
IntPtr pAPIVersion,
IntPtr pLineInitializeExParams);
There is some white cloud floating on the blue sky. That's the landscape I like.
|
|
|
|
|
Not too sure where the problem is. The first thing I'd do is get rid of the *, &, unsafe and fixed pointer stuff.
It's rarely needed as the built in marshaller can handle this stuff way better. I doubt it's the cause of your problems but declaring dwDevNum and creating a pointer from it's address is not going to work.
There are two keywords for passing value types by reference (thier pointer), ref and out .
If a value needs to be passed into a function then use ref . If the function doesn't need a value but there will be one there after the function returns then use out . In the case of dwDevNum this should be out but lpdwAPIVersion and dtParams should be ref . As IntPtr is a value type the pointer to a pointer for lphLineApp can be done using ref /out as well.
To the solution... have a look at this[^]. The guy says his C# code works.
|
|
|
|
|
I will study the code you provided. Thank you!
There is some white cloud floating on the blue sky. That's the landscape I like.
|
|
|
|
|
Dear all
I've got an issue with a COM interface I'm writing. I have to pass an array of c# objects back to VBScript and when I do I'm getting object required errors.
The com interface works like this
[ComVisible(true)]
public void findPatients(ref object MatchedPatients) {
List<object> mpList = retrievePatientList();
int arraySize = mpList.Count;
MatchedPatients = new object[arraySize];
MatchedPatients = mpList.ToArray();
}
The patient object is just a list of strings, i.e.
public class patientObject {
public string Key;
public string Surname;
public string Forename;
....
}
The COM interface is called by the following VBScript
dim j
o.findPatients j
Dim sOutput
sOutput = ""
For Each oPatient in j
' Code fails on the next line
sOutput = sOutput & oPatient.Surname
....
Next
If I step through the VBScript, variable j is getting assigned as an array of variants, the variable oPatient is assigned as an Object, but when I try and access any of the values within oPatient I'm getting an Object required error.
If anyone can offer any guidance it would be most appreciated, I'm tearing my hair out over this one.
UPDATE
I've fixed this issue now, it was surprisingly simple. All I had to do was make my object (PatientObject above) ComVisible and then VBScript could see the properties.
TO make a prairie it takes a clover and one bee,—
One clover, and a bee,
And revery.
The revery alone will do
If bees are few.
Emily Dickinson
modified on Tuesday, September 14, 2010 7:15 AM
|
|
|
|
|
Hi,
Is there a rather simple and constructive ways of validating a string value against a bunch value?
For example,
If I have a variable called "strStatus" it should only hold "In-Progress", "Closed" or "Open".
I know that I can do this using simple if condition or linq. Is there any other ways, like using enum etc.
Jack Sparrow
--------------------------------------
Defeat is not the worst of failures. Not to have tried is the true failure.
|
|
|
|
|
If the variable is only allowed to hold certain set of values, I wouldn't use string at all... An enum is the way to go. Enums can be converted to string easily and you can also parse a string to get the corresponding enum value.
If, for some reason you really need to use a string, there are several ways to validate it. Using a regular expression might be a good way to do it...
|
|
|
|
|
Yes an Enum should do the trick.
Jack Sparrow
--------------------------------------
Defeat is not the worst of failures. Not to have tried is the true failure.
|
|
|
|
|
To add to that, have a look atTips: Human readable strings for enum elements[^] which will let you use "In-Progress" as the string for the enum (normally you can't as enum elements must conform to normal C# variable name rules)
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|