I have written an application which calls methods from a dll written in C++. It is a WinForms application, which has a WCF service self-hosted in it. One of the WCF methods is
called in 2-3 seconds periodically. The problem does not occur when only the WCF part is executed. The problem does no appear when only the SDK functions are called. However if
I start the WCF client which calls my method periodically, and the same time I execute some SDK functions, after 10 seconds a FatalExecutionEngineError (System.ExecutionEngineException).
exception is raised and the application crashes. I really don't know what could be the problem, or how to solve it. I suspect it is somehow related with the SDK, but I'm not sure, just a
feeling. Reading the related answers here in SO, maybe the method-imports are wrong? Here is what I got so far:
WCF class:
[ServiceContract]
public partial interface IWCFSample
{
[OperationContract]
string GetData(string param);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public partial class WCFSample : IWCFSample
{
#region Delegates
public delegate string OnGetDataDelegate(object sender, string getDataParam);
#endregion Delegates
#region Events
public event OnGetDataDelegate OnGetData;
#endregion Events
public string GetData(string serializedGetDataParam)
{
string res = string.Empty;
try
{
if (OnGetData != null)
{
res = OnGetData(this, (serializedGetDataParam));
}
}
catch
{
throw;
}
return res;
}
}
Initiated like this:
private ServiceHost _serviceHost;
private WCFSample _samplewcf;
private void Form1_Load(object sender, EventArgs e)
{
_samplewcf = new WCFSample();
_samplewcf.OnGetData += samplewcfOnGetData;
_serviceHost = new ServiceHost(_samplewcf);
_serviceHost.Open();
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += (o, args) =>
{
WCFSampleClient client = new WCFSampleClient();
while (true)
{
if (bw.CancellationPending)
{
return;
}
client.GetData(DateTime.Now.ToString());
Thread.Sleep(200);
}
};
bw.RunWorkerAsync();
}
private string samplewcfOnGetData(object sender, string getDataParam)
{
richTextBox1.Text += "GetData Called - " + getDataParam + "\n";
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
return getDataParam;
}
The C++ related parts are pretty long, but here are the imports I use.
int OpenDevice (char* strUSBName, int iPortNum )
Imported as:
[DllImport("TP9000.dll")]
public static extern int OpenDevice(string USBNam, int portnum);
int CheckFeeder (int* nCheck)
Imported as:
[DllImport("TP9000.dll")]
public static extern int CheckFeeder(ref int pStatus);
int DP_GetSensorStatus (BYTE *pRailStatus, BYTE *pFeedRollerStatus, BYTE *pTraySensorState)
Imported as:
[DllImport("TP9000.dll")]
public static extern int DP_GetSensorStatus(ref byte pRailStatus, ref byte pFeedRollerStatus, byte[] pTraySensorState);
int PathSenser(int *pStatus)
Imported as:
[DllImport("TP9000.dll")]
public static extern int PathSenser(ref int p1);
int CheckRibbonEx( int *nRibbon, int *nTagRibbon)
Imported as:
[DllImport("TP9000.dll")]
public static extern int CheckRibbonEx(ref int nRibbon, ref int nTagRibbon);
int N_EndOfPrint(int nPanel, int *pPanelCount, int *pJobNo)
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_EndOfPrint(int p1, ref int p2, ref int p3);
int N_PrintJobStatus (int *pJobStatus )
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_PrintJobStatus(int[] p1);
UPDATE:
It seems that the last import is wrong:
int N_PrintJobStatus (int *pJobStatus )
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_PrintJobStatus(int[] p1);
If I don't call this function in my code, it does not hang. But how should I marshal it. The documentation says:
It checks the status of the printing.
int N_PrintJobStatus (int *pJobStatus )
Parameter pJobStatus[out]:
JobStatus[0] = Priter Status : idle(0x00), in printing(0x01), Error-Printing Stop(0xFF)
JobStatus[1] = No Standby Job (on Error, No pausing Job)
JobStatus[2] = the number of standby job (including the currently operating job)
JobStatus[3] = the number of copies of the currently operating job(total number of printing copies)
JobStatus[4] = the number of copies of the remaining jobs (Remaining Count)
JobStatus[5] = if the re-printig checking window displays or not. 1: AUTO Option display, 2:Manual option display, 0: No Checking Window
JobStatus[6] = it checks the error processing and status message level (1~4) then show 0t at retprinting checking window(Auto Option)
Open the printer and then check the ribbon.
Card is ejecting
Ribbon is being synchronized
If you want to re-print, please press “OK” button.( make “OK” button activated)
Return value 0: Success. -1: Failure. (Get_Status)
Okay, without the rest of the code it was impossible to solve this. The wrong code was the following:
int[] nJobSt = { 0, 0, 0, 0, 0, 0 }; //notice that the array length is 6
LastErrorCode = TP9000Dll.N_PrintJobStatus(nJobSt);
From the SDK documentation we should assume the function needs an array length of 7
So the correct code is:
int[] nJobSt = { 0, 0, 0, 0, 0, 0, 0 }; //notice that the array length is 7
LastErrorCode = TP9000Dll.N_PrintJobStatus(nJobSt);
The conclusion: Read every documentation 3 times, never trust the sample applications which are coming with the SDK.
Related
I'm working on a driver for a scanner. Got dll and header files from provider, aside of a manual in PDF, written in native C++ (dont have source code). Need to use it within a C# project but I'm having problems with the structs (either trying to read or send them).
I got the dll methods using the Command Prompt, demangling them in a website (since it has +100). Of course, I wont use all of them, just the ones I need. Didn't have problems with the ones using primitive data types, in fact, made the scanner turn on/off, scan and such.
My main problem is the following: I need to set some parameters, because with the default ones I'm not getting the needed info (and that's the MOST important thing I need, actually). The only way to do it is with a method that include 2 params: the ID (just an int) and the setting (an struct). That struct has internally not one, but 2 different structs instances (and one of them is an array, within another kind of struct as one of the params). In other words, gonna need to work with 4 different structs.
I declared all my structs, following the template provided in the .h file, and inmported the method. When I try to do a test it keeps giving me an error. I believe the problem is the array of structs. I tried with a normal passing, Marshaling, using a pin to array, changing data type, adding a "MarshalAs" with all bool vars... nothing seems to work.
Been trying to solve this for days already. Dont know what am I doing wrong (because this is my first time importing methods). I read about the C++/Cli thing but never worked with that either.
See code below (I kinda modified a little because of confidentiality of the information)
This is how is defined in the .h file (C++)
// The structs (won't add all parameters, but are basically the same type)
typedef struct _ImParam
{
UINT Format;
UINT Resolution;
UINT ColorDepth;
} IM_PARAM;
typedef struct _sValues
{
UINT Xpos;
UINT Ypos;
UINT Width;
UINT Height;
BOOL Milli;
} S_VALUES;
typedef struct _sProperties
{
BOOL Enable;
S_VALUES Properties;
} S_PROPERTIES;
typedef struct _DevParam
{
BOOL Enable;
UINT Font;
char Symbol;
IM_PARAM Image1;
IM_PARAM Image2;
S_PROPERTIES Properties[10];
UINT FeedMode;
} DevParam;
// more code, comments, etc. etc.
// This is how is defined
BOOL SetParameters( DWORD ID, DevParams DParam )
This is how I build the structs in C#
[StructLayout(LayoutKind.Sequential)]
public struct ImParam
{
public uint Format;
public uint Resolution;
public uint ColorDepth;
public ImParam(uint n)
{
Format = n;
Resolution = 300;
ColorDepth = 256;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sValues
{
public uint Xpos;
public uint Ypos;
public uint Width;
public uint Height;
public bool Milli;
public sValues(uint n)
{
Xpos = n;
Ypos = n;
Width = n;
Height = n;
Milli = false;
}
};
[StructLayout(LayoutKind.Sequential)]
public struct sProperties
{
public bool Enable;
public sValues Properties;
public sProperties(int n)
{
Enable = false;
Front = false;
Properties = new sValues(n);
}
};
// Commented code is from another attemp
[StructLayout(LayoutKind.Sequential)]
public struct DevParam
{
public bool Enable;
public uint Font;
public char Symbol;
public ImParam Image1;
public ImParam Image2;
public IntPtr Properties;
//public sProperties[] Properties;
public uint FeedMode;
public DeviceParameters(IntPtr SnP) //(int n)
{
Enable = true;
Font = 0;
Symbol = '?';
Image1 = new ImParam(3);
Image2 = new ImParam(3);
Properties = SnP;
/*Properties = new sProperties[n];
*for(int i = 0; i < n; i++)
* Properties[i] = new sProperties(0);*/
FeedMode = 1;
}
};
// .dll file path definition, some methods imported, etc. etc.
[DllImport(path, EntryPoint = "?SetParameters##YGHKU_DevParam###Z")]
public static extern bool SetParameters(int ID, DevParam dParam);
And this is when I do call it (added commented code to show you my attemps)
static void Main(string[] args)
{
bool res = false;
int ID;
sProperties[] SnP = new sProperties[10];
for (int i = 0; i < 10; i++)
SnP[i] = new sProperties(0);
try
{
// Some code to turn on scanner, get ID value and such
/* Attemp1: Passing the struct normaly.
* Result: ArgumentException [HRESULT: 0x80070057 (E_INVALIDARG))]
* try
* {
* DevParam dParam = new DevParam(10);
* res = Class1.SetParameters(ID, dParam);
* Console.WriteLine(res);
* }
* catch (Exception e) { Console.WriteLine(e); }*/
/* Attemp2: Marshaling each element of the array.
* Result: The managed PInvoke signature doesnt mach the destination one
* int S = Marshal.SizeOf(typeof(sProperties));
* DevParam dParam = new DevParam(Marshal.AllocHGlobal(SnP.Length*S));
* IntPtr ptr = dParam.Properties;
* for (int i = 0; i < SnP.Length; i++)
* {
* Marshal.StructureToPtr(SnP[i], ptr, false);
* ptr += S;
* }
* try
* {
* res = Class1.SetDevParam(ID, dParam);
* Console.WriteLine(res);
* }
* finally { Marshal.FreeHGlobal(dParam.sProperties); }*/
/* Attemp3: Adding a Pin Pointer to struct
* Result: Exception (Object has no primitive data and it can't
* be transfered into bits blocks) */
GCHandle SpHandle = GCHandle.Alloc(SnP, GCHandleType.Pinned);
try
{
DevParam dParam = new DevParam(SpHandle.AddrOfPinnedObject());
res = Class1.SetParameters(ID, dParam);
Console.WriteLine(res);
}
catch (Exception e) { Console.WriteLine(e); }
finally { SpHandle.Free(); }
// More code for testing other methods and blahblahblah
}
catch (Exception e) { Console.WriteLine(e); }
Console.WriteLine("Finished");
Console.ReadKey();
}
What do I expect? Getting just a boolean result to see if method executed sucessfully (and of course, if true, scanner should have defined the new parameters)
What do I get? A bunch of exceptions.
Please, any help would be great. Thanks in advance.
PD: Sorry for that long post.
PD2: I'm quite rockie, so please try to explain it "for dummies"
Thanks Hans. Seems it worked!
Just modiffied the struct as suggested:
[StructLayout(LayoutKind.Sequential)]
public struct DevParam
{
public bool Enable;
public uint Font;
public char Symbol;
public ImParam Image1;
public ImParam Image2;
//public IntPtr Properties;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public sProperties[] Properties;
public uint FeedMode;
public DeviceParameters(int n) //(IntPtr SnP)
{
Enable = true;
Font = 0;
Symbol = '?';
Image1 = new ImParam(3);
Image2 = new ImParam(3);
//Properties = SnP;
Properties = new sProperties[n];
for(int i = 0; i < n; i++)
Properties[i] = new sProperties(0);
FeedMode = 1;
}
};
And used the "Attemp1" code.
I have this school assignment where we are required to make a DLL based on some a Win32 sound player/recorder and then tie it into a C# application we already made that edits sound files. I have it so if you record with the DLL it puts the recorded sound file into the main program using Marshal.Copy to copy the unmanaged byte[] from the DLL to a managed byte[] in the main program which then converts the values into shorts, which works perfectly fine. However, I would also like to do the reverse. That is to say, I would like to be able to pass a byte[] into the DLL to be played, since it currently only plays the sounds that it recorded. I looked through the documentation on the Marshal class and didn't find anything useful so I'm not sure how to go about doing this. This program is quite massive so far so I'll try to only post the relevant code. The set up I have in the DLL uses an invisible CallBack window that handles the WIM and WOM messages sent by the functions that are called outside the DLL.
The Main Program:
[DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
public static extern IntPtr getBytes();
[DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
public static extern int getNumBytes();
//I thought I could use something like this to set it
[DllImport("RecordDll.dll", CharSet = CharSet.Auto)]
public static extern void setBytes(IntPtr wav);
short[] storedRecording;
//Constructor plus a ton of other irrelevant stuff here
private void RecordStart_Click(object sender, EventArgs e){
RecordStart.Enabled = false;
PlayStart.Enabled = false;
Stop.Enabled = true;
Stop.Focus();
RecordStatus.Text = "";
recordStart(); //DLL function
}
private void StopRecord_Click(object sender, EventArgs e){
recordEnd(); //DLL function
int numBytes = getNumBytes();
byte[] byteArr = new Byte[numBytes];
storedRecording = new short[numBytes];
Marshal.Copy(getBytes(), byteArr, 0, numBytes);
for (int i = 0; i < numBytes; i++)
{
storedRecording[i] = byteArr[i];
}
RecordStatus.Text = "Recording loaded.";
}
private void PlayStart_Click(object sender, EventArgs e){
PlayStart.Enabled = false;
PlayPause.Enabled = true;
Stop.Enabled = true;
Stop.Focus();
RecordStatus.Text = "";
if(storedRecording != null){
//convert the array to an unmanaged byte[] somehow?
//then call setBytes with that byte[]?
}
playBegin(); //DLL function
}
The Relevant Fucntions From The Record/Play DLL:
static PBYTE* pSaveBuffer;
__declspec(dllexport) BOOL CALLBACK playBegin() {
// Open waveform audio for output
waveform.wFormatTag = WAVE_FORMAT_PCM;
waveform.nChannels = 1;
waveform.nSamplesPerSec = 11025;
waveform.nAvgBytesPerSec = 11025;
waveform.nBlockAlign = 1;
waveform.wBitsPerSample = 8;
waveform.cbSize = 0;
if (waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveform,
(DWORD)myHwnd, 0, CALLBACK_WINDOW))
{
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(myHwnd, szOpenError, szAppName,
MB_ICONEXCLAMATION | MB_OK);
}
return TRUE;
}
__declspec(dllexport) PBYTE* CALLBACK getBytes() {
return pSaveBuffer;
}
__declspec(dllexport) int CALLBACK getNumBytes() {
return dwDataLength;
}
From The WinProc That Is Used To Handle The waveOutOpen Message Sent To The CallbackWindow In The DLL:
case MM_WOM_OPEN:
// Set up header
pWaveHdr1->lpData = (LPSTR)*pSaveBuffer;
pWaveHdr1->dwBufferLength = dwDataLength;
pWaveHdr1->dwBytesRecorded = 0;
pWaveHdr1->dwUser = 0;
pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
pWaveHdr1->dwLoops = dwRepetitions;
pWaveHdr1->lpNext = NULL;
pWaveHdr1->reserved = 0;
// Prepare and write
waveOutPrepareHeader(hWaveOut, pWaveHdr1, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, pWaveHdr1, sizeof(WAVEHDR));
bEnding = FALSE;
bPlaying = TRUE;
return 0;
Hopefully that communicates sort of how it works. Despite the huge amount of code, I'm pretty sure the problem is a small one. I just need to be able to set *pSaveBuffer to contain the data from the main program. I have a feeling this could be done by converting the managed array to an unmanaged array, but like I said I have no idea if that's even possible or not. Any help with this problem would be greatly appreciated!
I am having a problem using the ThreeSpace_API.dll whilst trying to add support for the sensor to freePIE. Using the polling method is working fine. However I am having an issue with streaming.
Using VS 2012 this works absolutely fine. However after building and trying to run through the executable it crashes with the following error:
Application: FreePIE.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at FreePIE.Core.Plugins.Yei3Space.Api.tss_getLastStreamData(Int32, FreePIE.Core.Plugins.Yei3Space.TssStreamPacket ByRef, Int32)
at FreePIE.Core.Plugins.Yei3Space.Api.UpdateQuaternion(Int32, FreePIE.Core.Plugins.SensorFusion.Quaternion)
at FreePIE.Core.Plugins.Yei3SpaceGlobalHolder.Update()
It is called in the following way:
//DLL Call to ThreeSpace_API.dll
[DllImport("ThreeSpace_API.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern TssError tss_getLastStreamData(int id, out TssStreamPacket packet, int size);
//Stream Packet Struct
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TssStreamPacket
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public float[] quat;
}
// Starts streaming asynchronous data
public static void StartStreamingU(int device_id)
{
int count;
byte[] stream_slots = new byte[8];
stream_slots[0] = (byte)TssStreaming.TSS_GET_TARED_ORIENTATION_AS_QUATERNION;
stream_slots[1] = (byte)TssStreaming.TSS_NULL;
stream_slots[2] = (byte)TssStreaming.TSS_NULL;
stream_slots[3] = (byte)TssStreaming.TSS_NULL;
stream_slots[4] = (byte)TssStreaming.TSS_NULL;
stream_slots[5] = (byte)TssStreaming.TSS_NULL;
stream_slots[6] = (byte)TssStreaming.TSS_NULL;
stream_slots[7] = (byte)TssStreaming.TSS_NULL;
count=0;
if( !is_streaming )
{
while( count < 3 )
{
if( tss_setStreamingTiming(device_id,0,-1,1500000) == 0 )
{
if( tss_setStreamingSlots(device_id,stream_slots) == 0 )
{
if( tss_startStreaming(device_id) == 0 )
{
is_streaming=true;
break;
}
}
}
count++;
}
}
}
public static TssError UpdateQuaternion(int deviceId, Quaternion quaternion)
{
uint timestamp;
float[] fltQuat = new float[4];
TssStreamPacket packet = new TssStreamPacket();
TssError error = TssError.TSS_NO_ERROR;
if(is_streaming)
{
try
{
error = tss_getLastStreamData(deviceId, out packet, 16);
fltQuat[0] = packet.quat[0];
fltQuat[1] = packet.quat[1];
fltQuat[2] = packet.quat[2];
fltQuat[3] = packet.quat[3];
}
catch (System.AccessViolationException e)
{
return TssError.TSS_ERROR_READ;
}
}
}
The annoying thing is that it works fine through debugger so there is not much I can do to test this. I have tried various alternatives to marshalling the data back. Interestingly doing this via a normal float array seems to block the CPU.
Any advice would be most appreciated.
The wrapper is missing the timestamp parameter.
This is the declaration from yei_threespace_api.
TSS_EXPORT TSS_Error tss_getLastStreamData(TSS_Device_Id device, char * output_data, unsigned int output_data_len, unsigned int * timestamp);
Tested and now working fine!
So I try to communicate c# code in unity and objective c code in Xcode.
Here is my code:
text.h
extern "C" {
int textTotexture(int hello,int world);
}
text.mm
int textTotexture(int hello,int world){
NSString *myString =[[NSString alloc] init];
NSSize size = [myString sizeWithAttributes:0];
NSImage* newImage = [[NSImage alloc] initWithSize: size];
[newImage lockFocus];
/* if you have a second image you're going to overlay on top of the first, do the same except use NSCompositeSourceOver as the operation */
//NSRect myRect = NSMakeRect(0,0,size.width,size.height);
//[myString drawInRect:myRect withAttributes:0];
[newImage unlockFocus];
//NSData *imageData = [newImage TIFFRepresentation];
//NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
//NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
//imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps];
//int len = [imageData length];
//memcpy(data, [imageData bytes], len);
return hello+world;
}
calling function:
[DllImport("CubePlugin")]
public static extern int textTotexture(int s, int w);
Debug.Log(textTotexture(1,2));
The basic communication is fine as debug log returns 3. but as soon as I add functional code in, the unity just crashes. I suspect some of the native code just doesn't run to the end.
I just found out the issue occurs when I add lock focus and lose focus back in. What shall I do to avoid doing this but achieve my goal?
its not obvious how your are handling your class "text" but you can try this: (I am writing without editor so there might be typos)
#implementation text
//....
-(int)textToTexture:(int)A andValue:(int)B
{
int result = 0;
// do stuff
return result
}
#end
static text* myObject = nil;
extern "C"{
int textToTexture(int a, int b)
{
if(myObject == nil)
myObject = [[text alloc] init];
return [myObject textToTexture:a andValue:b];
}
}
inside your C# file
[DllImport ("__Internal")]
public static extern int textTotexture(int a, int b);
then call the function
C++ Function header in DLL this two function to get some information about the wifi stations around me using win mobile 6.5 device and i need to invoke them to use them in C# code
// (adapter names , pointer to destination buffer ,and the size , returned structs)
bool __declspec(dllexport) GetBBSIDs(LPWSTR pAdapter, struct BSSIDInfo *pDest, DWORD &dwBufSizeBytes, DWORD &dwReturnedItems);
bool __declspec(dllexport) RefreshBSSIDs(LPWSTR pAdapter);
bool __declspec(dllexport) GetAdapters(LPWSTR pDest, DWORD &dwBufSizeBytes);
C# sample
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "GetAdapters", SetLastError = true)]
public static extern bool getAdapters([MarshalAs(UnmanagedType.LPWStr)] String buf, ref UInt32 dwBufSizeBytes);
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "RefreshBSSIDs", SetLastError = true)]
public static extern bool refreshBSSIDs([MarshalAs(UnmanagedType.LPWStr)]String buf);
[DllImport(#"\Storage Card\Work\Beaad.dll", EntryPoint = "GetBBSIDs", SetLastError = true)]
public static extern bool getBBSIDs([MarshalAs(UnmanagedType.LPWStr)]String buf,BSSIDInfo [] nfo, ref UInt32 dwBufSizeBytes, ref UInt32 dwReturnedItems);
[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
public struct BSSIDInfo
{
public byte[] BSSID; //mac
public char[] SSID;
public BSSIDInfo(byte[]bs,char[] ss)
{
this.RSSI = 0;
this.Infastructure = 0;
this.Channel = 0;
this.Auth = 0;
bs = new byte[6];
ss = new char[32];
BSSID = bs;
SSID = ss;
}
public int RSSI;
public int Channel;
public int Infastructure;
public int Auth;
}
public static byte[] StrToByteArray(string str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(str);
}
public static char[] c = new char[1024];
string buf = new string(c);
public void button1_Click(object sender, EventArgs e)
{
BSSIDInfo[] nfo = new BSSIDInfo[128];
byte[] bytee=StrToByteArray(buf);
UInt32 dwsize= new UInt32();
UInt32 dwTmp = new UInt32();
UInt32 dwCount = new UInt32();
dwTmp = Convert.ToUInt32(Marshal.SizeOf(typeof(BSSIDInfo)) * nfo.Length);
dwCount =0;
dwsize=Convert.ToUInt32(bytee.Length);
if (false == getAdapters(buf,ref dwsize) || dwsize == 0)
{
label1.Text = "no adabters";
}
else
{
String [] strList=new String[15];
if (buf.Contains(',') == false)// one adapter
{
textBox1.Text = buf;
}
else
{
strList = buf.Split(',');
for (int i = 0; i < strList.Length; i++)
{
textBox1.Text+= strList[i]+Environment.NewLine;
}
}
if (refreshBSSIDs(buf) && getBBSIDs(buf, nfo, ref dwTmp, ref dwCount) && dwCount > 0)
{
//refreshBSSIDs(buf) &&
for (int i = 0; i < dwCount; i++)
{
textBox2.Text += nfo.GetValue(i).ToString() + Environment.NewLine;
}
}
else
{
//make another thing
}
}
}
and when i put this dll on the mobile and the C# app.exe the first function that named as Getadapters(..) return to me the name of the adapter in the first textbox1 then the app stopped and give me not supported exception when the mobile tries to execute the other two function that named as refreshBSSID() and getBSSIDs() so what is the problem ? or is there another solution to get this information (BSSID ,SS ..etc) ?
C++ by default unless changed uses a caller( Cdecl ) calling convention. Your C++ code does not change the calling convention. Your C# code by default ( unless you change it ) will use a callee convention ( StdCall ).
While this might not be exactly the problem your having it still is technically incorrect. Even if you were to fix your current problem you likely will end up having a problem because of the calling convention.
I am going to guess your C# BSSIDInfo structure does not match the C++ structure. Why do the method StrToByteArray when all it does is GetBytes on the given string...
when the mobile tries to execute the
other two function that named as
refreshBSSID() and getBSSIDs() so what
is the problem ? or is there another
solution to get this information
I thought I knew the reason took another look and I was wrong.