c#


How can I declare a pointer to a struct for P/Invoke?


I'm trying to use P/Invoke Interop Assistant to call a C++ Dll in C#. Most of the header is converted fine but I'm having trouble with this:
#define FULLOCTAVE_BINS 12
#define THIRDOCTAVE_BINS 36
typedef struct tagTimeHistory
{
UINT m_nAction;
int m_nFlag;
int m_nRecordNum;
int m_nTimeStamp;
int m_nMiscStartIndex;
float m_pfTHFloatVals[256]; // Number of valid values given by m_nNumFloatVals in Settings.
float m_pfTH11OBAVals[4][FULLOCTAVE_BINS]; // 0-4 spectra given by m_nNumOBA11Vals in Settings
float m_pfTH13OBAVals[4][THIRDOCTAVE_BINS]; // 0-4 spectra given by m_nNumOBA13Vals in Settings
float m_fDuration;
} stTimeHistory_t;
typedef struct tagSlmBulkRecords
{
int nRecType;
union
{
stTimeHistory_t *m_ThRecs;
stInterval_t *m_Interval;
stExceedence_t *m_Exceedences;
stRunRecord_t *m_RunRecord;
stSpeechData_t *m_VoiceRecord;
stSpeechData_t *m_AudioRecord;
};
} stSlmBulkRecord_t;
This is being converted to:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
public struct Anonymous_d2bf9406_c664_4664_9196_800cc23f445a {
/// stTimeHistory_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_ThRecs;
/// stInterval_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_Interval;
/// stExceedence_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_Exceedences;
/// stRunRecord_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_RunRecord;
/// stSpeechData_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_VoiceRecord;
/// stSpeechData_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_AudioRecord;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tagSlmBulkRecords {
/// int
public int nRecType;
/// Anonymous_d2bf9406_c664_4664_9196_800cc23f445a
public Anonymous_d2bf9406_c664_4664_9196_800cc23f445a Union1;
}
But how do I use m_ThRecs when it's just a System.IntPtr? Is there some way of explicitly declaring it to be a pointer to stTimeHistory_t? The C++ code I'm porting to C# uses it like this:
stSlmBulkRecord_t bulkRecord;
bulkRecord.m_ThRecs = new stTimeHistory_t[dataCounts.m_nNumTH];
but if I try this in C#:
tagSlmBulkRecords bulkRecord;
bulkRecord.Union1.m_ThRecs = new tagTimeHistory[dataCounts.m_nNumTH];
I get:
Error 1 Cannot implicitly convert type 'SlmTest.Program.tagTimeHistory[]' to 'SlmTest.Program.tagTimeHistory'"
If I try an unsafe definition:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct tagTimeHistory
{
/// UINT->unsigned int
public uint m_nAction;
/// int
public int m_nFlag;
/// int
public int m_nRecordNum;
/// int
public int m_nTimeStamp;
/// int
public int m_nMiscStartIndex;
/// float[256]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 256, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)]
public float[] m_pfTHFloatVals;
/// float[48]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 48, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)]
public float[] m_pfTH11OBAVals;
/// float[144]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 144, ArraySubType = System.Runtime.InteropServices.UnmanagedType.R4)]
public float[] m_pfTH13OBAVals;
/// float
public float m_fDuration;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
public unsafe struct Anonymous_d2bf9406_c664_4664_9196_800cc23f445a
{
/// stTimeHistory_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public tagTimeHistory *m_ThRecs;
/// stInterval_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr *m_Interval;
/// stExceedence_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_Exceedences;
/// stRunRecord_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_RunRecord;
/// stSpeechData_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_VoiceRecord;
/// stSpeechData_t*
[System.Runtime.InteropServices.FieldOffsetAttribute(0)]
public System.IntPtr m_AudioRecord;
}
I get:
error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type
If you really want to interoperate with the native code, you can use the fixed operator:
var array = new tagTimeHistory[dataCounts.m_nNumTH];
fixed (tagTimeHistory* ptr = array)
{
// do anything with the raw pointer
}
Note that fixed operator and pointer types in C# requires unsafe capability. And you may want to replace IntPtrs with the proper pointer types for more type safety (although there is a method for converting pointers to IntPtrs and back).
Another way of doing the same is through the methods of Marshal class.
EDIT. Here is a sample of the revised unsafe definition of your funny named union structure:
[StructLayout(LayoutKind.Explicit)]
public unsafe struct Anonymous_d2bf9406_c664_4664_9196_800cc23f445a
{
[FieldOffset(0)]
public stTimeHistory_t* m_ThRecs;
[FieldOffset(0)]
public stInterval_t* m_Interval;
[FieldOffset(0)]
public stExceedence_t* m_Exceedences;
[FieldOffset(0)]
public stRunRecord_t* m_RunRecord;
[FieldOffset(0)]
public stSpeechData_t* m_VoiceRecord;
[FieldOffset(0)]
public stSpeechData_t* m_AudioRecord;
}
You should define all structures such as stTimeHistory_t in your code (or replace the ones you don't care with generic IntPtrs).
And regarding creation of structure array with Marshal: native memory pool have no such concept as structure array; all it care is only bytes. So you may, for example, use the Marshal.AllocHGlobal method:
IntPtr myPtr = Marshal.AllocHGlobal(Marshal.SizeOf<tagTimeHistory>() * dataCounts.m_nNumTH);
// ... write something to an array, use it
// And don't forget to free it to prevent memory leaks!
Marshal.FreeHGlobal(myPtr);
EDIT 2. Regarding the "Cannot take the address of, get the size of, or declare a pointer to a managed type" error - your definition is not fully unmanaged. Unsafe definitions and the ones using the marshaling logic are not always equal; here it thinks your class is "managed" because of array references in it. Try fixed arrays:
[StructLayout(LayoutKind.Sequential)]
public unsafe struct tagTimeHistory
{
public uint m_nAction;
public int m_nFlag;
public int m_nRecordNum;
public int m_nTimeStamp;
public int m_nMiscStartIndex;
public fixed float m_pfTHFloatVals[256];
public fixed float m_pfTH11OBAVals[48];
public fixed float m_pfTH13OBAVals[144];
public float m_fDuration;
}

Related Links

C# code won't launch programs. Win32Exception was unhandled
FindControl cannot find checkbox in c#
Make Combined Images keep their Transparent BackGround
Open file in intranet from another server - ASP.Net C#
Get listView item number from selected item in wpf and c#
asp.net web deployment and hosting
Preserve user folder location on browse for image?
C# parse non uniform bit sequences from array of bytes
Boxing and unboxing is a myth?
Create Notification Hub - REST only (no SDK)
Updating two labels in two different WPF Windows
C# Method overloading resolution [duplicate]
How to include a console executable with a forms application?
How to change the preview window style in VS2013
What is the Windows phone control used in
Switch Row/Column (switch axes) in xlsio chart (syncfusion)

Categories

HOME
optimization
azure-active-directory
wifi
abc
gap-system
liquibase
x86-64
checkpoint
virtualhost
olap
suitecrm
aspectj
watson-dialog
logstash-configuration
repeater
swift3.1
facebook-marketing-api
pylint
template10
css-float
alert
md2
sonarlint
google-drive-android-api
connection-pooling
email-client
ckeditor4.x
datanucleus
pydub
resx
custom-fields
git-submodules
federated
xlib
intermec
boost-log
multilanguage
opencsv
ios-autolayout
tikz
oracle-nosql
flickr
voyager
restler
geocomplete
iterm2
var
byobu
google-chrome-console
compiled-query
wufoo
npoco
xmldom
remap
emacs24
openidm
visio-2010
bioperl
aws-rds
richtext
xamarin-test-cloud
try-catch-finally
grib
esprima
scikit-image
dbi
class-design
kik
treelist
periodic-processing
abstract
wordpress-plugin
jquery-draggable
web-performance
matlab-engine
gtkwave
ios8-share-extension
webservices-client
page-flipping
vanilla-forums
bootstrap-tabs
roslyn-code-analysis
clearquest
waterline
valdr-bean-validation
connection-timeout
xmla
method-overloading
cocos2d-x-2.x
pnunit
cs193p
opencobol
farpoint-spread
pidgin
slimscroll
kuka-krl
android-jack-and-jill
ekevent
dylan
ojb
caroufredsel
angularjs-select2
qgraphicsscene
friendly-url
asp.net-4.0
coinbase-php
setcookie
boost.build
urlfetch
feincms
maven-eclipse-plugin
rjs
zipstream
meego-harmattan
lwp
javah
table-valued-parameters
large-data-volumes
carbon-emacs
ihtmldocument2
djangoappengine
unauthorized

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile