PInvoke an old DLL file

G

gregarican

I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:

#include <acs.h>
#include <csta.h>

RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */

How do I create a C# struct that contains members that are packed
pointers?
 
N

Nicholas Paldino [.NET/C# MVP]

You are going to have to create a structure which has IntPtr members
which act as the pointers.

Once you do that, you will also have to define the structures/types that
the pointers point to.

If you have to allocate the memory for these structures before you pass
the structure to the function through P/Invoke, you will have to use one of
the static Alloc* methods on the Marshal class in order to allocate memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.

On return, you have to pass those pointers to the PtrToStructure method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.
 
G

gregarican

You are going to have to create a structure which has IntPtr members
which act as the pointers.

Once you do that, you will also have to define the structures/types that
the pointers point to.

If you have to allocate the memory for these structures before you pass
the structure to the function through P/Invoke, you will have to use one of
the static Alloc* methods on the Marshal class in order to allocate memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.

On return, you have to pass those pointers to the PtrToStructure method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:
#include <acs.h>
#include <csta.h>
RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */
How do I create a C# struct that contains members that are packed
pointers?- Hide quoted text -

- Show quoted text -

Ouch. Sounds like some serious groundwork to get things started. But I
have to do it in any event. Could you please post a brief sample of
unsafe code that could achieve what I'm looking to do with this basic
structure that I listed? That should be enough to get my head around
this and get started. I'd really appreciate it :)
 
N

Nicholas Paldino [.NET/C# MVP]

You would need to post the typedefs or structure definitions for the
members in the structure which are not standard types (what is Rescode_t for
example).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

gregarican said:
You are going to have to create a structure which has IntPtr members
which act as the pointers.

Once you do that, you will also have to define the structures/types
that
the pointers point to.

If you have to allocate the memory for these structures before you
pass
the structure to the function through P/Invoke, you will have to use one
of
the static Alloc* methods on the Marshal class in order to allocate
memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.

On return, you have to pass those pointers to the PtrToStructure
method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:
#include <acs.h>
#include <csta.h>
RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */
How do I create a C# struct that contains members that are packed
pointers?- Hide quoted text -

- Show quoted text -

Ouch. Sounds like some serious groundwork to get things started. But I
have to do it in any event. Could you please post a brief sample of
unsafe code that could achieve what I'm looking to do with this basic
structure that I listed? That should be enough to get my head around
this and get started. I'd really appreciate it :)
 
G

gregarican

You would need to post the typedefs or structure definitions for the
members in the structure which are not standard types (what is Rescode_t for
example).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




You are going to have to create a structure which has IntPtr members
which act as the pointers.
Once you do that, you will also have to define the structures/types
that
the pointers point to.
If you have to allocate the memory for these structures before you
pass
the structure to the function through P/Invoke, you will have to use one
of
the static Alloc* methods on the Marshal class in order to allocate
memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.
On return, you have to pass those pointers to the PtrToStructure
method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:
#include <acs.h>
#include <csta.h>
RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */
How do I create a C# struct that contains members that are packed
pointers?- Hide quoted text -
- Show quoted text -
Ouch. Sounds like some serious groundwork to get things started. But I
have to do it in any event. Could you please post a brief sample of
unsafe code that could achieve what I'm looking to do with this basic
structure that I listed? That should be enough to get my head around
this and get started. I'd really appreciate it :)- Hide quoted text -

- Show quoted text -

Gotcha. It is like peeling an onion since the struct members are
themselves other custom datatypes. Typically enums or shorts. I think
I have a basic understanding enough to at least Google my way to
getting a crack at this. Thanks for the high level overview that at
least has me pointed in the right direction!
 
B

Ben Voigt

gregarican said:
You are going to have to create a structure which has IntPtr members
which act as the pointers.

Once you do that, you will also have to define the structures/types
that
the pointers point to.

If you have to allocate the memory for these structures before you
pass
the structure to the function through P/Invoke, you will have to use one
of
the static Alloc* methods on the Marshal class in order to allocate
memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.

On return, you have to pass those pointers to the PtrToStructure
method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)




I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:
#include <acs.h>
#include <csta.h>
RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */
How do I create a C# struct that contains members that are packed
pointers?- Hide quoted text -

- Show quoted text -

Ouch. Sounds like some serious groundwork to get things started. But I
have to do it in any event. Could you please post a brief sample of
unsafe code that could achieve what I'm looking to do with this basic
structure that I listed? That should be enough to get my head around
this and get started. I'd really appreciate it :)

It would be much easier to use C++/CLI to interact with this legacy code,
because you can just include the header file and use the existing structure
definitions, and access native memory directly. Then, C++/CLI generates
..NET metadata for whatever functions you write, so then you can call C++/CLI
from C# just like you would any other .NET library.
 
G

gregarican

You are going to have to create a structure which has IntPtr members
which act as the pointers.
Once you do that, you will also have to define the structures/types
that
the pointers point to.
If you have to allocate the memory for these structures before you
pass
the structure to the function through P/Invoke, you will have to use one
of
the static Alloc* methods on the Marshal class in order to allocate
memory
(or use unsafe code, which would make it a lot easier) and then set the
values of those fields to the blocks of memory that you allocated.
On return, you have to pass those pointers to the PtrToStructure
method
to read the unmanaged memory and return a managed representation to you.
Again, unsafe code would probably be very helpful here, as you could just
access the pointers in memory directly.
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I am trying to port a legacy CTI application written in another
programming language to C# 2005. From my initial research into it I
see I can utilize the DllImport method to tap into the DLL file (which
is CTSA32.DLL). From there I have documented API for the various C
methods that are invoked, most all of which have an in and an out. You
pass in a data structure and get a data structure returned back.
What's the most straightforward way of mimicing the packed pointers
that are in these C data structures? The other data types I think I
have a handle on. Most of them are unsigned short or else enums. But
the packed pointers seems to be another matter? Here's a sample data
structure that opens the initial CTI session stream:
#include <acs.h>
#include <csta.h>
RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */
How do I create a C# struct that contains members that are packed
pointers?- Hide quoted text -
- Show quoted text -
Ouch. Sounds like some serious groundwork to get things started. But I
have to do it in any event. Could you please post a brief sample of
unsafe code that could achieve what I'm looking to do with this basic
structure that I listed? That should be enough to get my head around
this and get started. I'd really appreciate it :)

It would be much easier to use C++/CLI to interact with this legacy code,
because you can just include the header file and use the existing structure
definitions, and access native memory directly. Then, C++/CLI generates
.NET metadata for whatever functions you write, so then you can call C++/CLI
from C# just like you would any other .NET library.- Hide quoted text -

- Show quoted text -

Easier is good :) Looking through all of the Pinvoke hoops I would
have to jump through the task does seem daunting. I haven't used C++/
CLI before so I will start digging in on this tomorrow. Thanks for the
tip!
 

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

Similar Threads

More PInvoke Shenanigans 2

Top