How to convert C# string[] to System.IntPtr? - c#

I need to use a native dll struct in my application.
struct da_i2k_input_file_info in the dll .h file is
struct DA_I2K_EXPORT_API da_i2k_input_file_info {
const WDCHAR * image_path;
const WDCHAR ** image_files;
int num_images;
};
and this is what user code might look like if written in C++
in_file_info.num_images = 3;
in_file_info.image_files = new const WDCHAR*[in_file_info.num_images];
in_file_info.image_files[0] = WSTR("IMG_8670.JPG");
in_file_info.image_files[1] = WSTR("IMG_8671.JPG");
in_file_info.image_files[2] = WSTR("IMG_8672.JPG");
But this C# code
[StructLayout(LayoutKind.Sequential)]
public struct da_i2k_input_file_info
{
[MarshalAs(UnmanagedType.LPTStr)]
public string image_path;
public IntPtr image_files;
public int num_images;
}
var openFileDialog = new OpenFileDialog{Multiselect = true};
da_i2k_input_file_info in_file_info;
in_file_info.image_path = null; // use full path in .image_files
in_file_info.num_images = openFileDialog.FileNames.Length;
in_file_info.image_files = openFileDialog.FileNames;
Causes this error
Cannot implicitly convert type 'string[]' to 'System.IntPtr'
Casting openFileDialog.FileNames as IntPtr does not help.
How can I load in_file_info.image_files from openFileDialog.FileNames?
Edit: OP cross posted this here

I believe you need to change you struct to be as follows:
[StructLayout(LayoutKind.Sequential)]
public struct da_i2k_input_file_info
{
[MarshalAs(UnmanagedType.LPTStr)]
public string image_path;
[MarshalAs(UnmanagedType.LPArray)]
public string[] image_files;
public int num_images;
}

A working answer was posted here.
Code follows.
(included by tomfanning)
private static void DoTest()
{
var openFileDialog = new OpenFileDialog { Multiselect = true };
da_i2k_input_file_info in_file_info;
openFileDialog.ShowDialog();
in_file_info.image_path = null; // use full path in .image_files
in_file_info.num_images = openFileDialog.FileNames.Length;
// Create an array of IntPtrs.
IntPtr[] image_files_array = new IntPtr[in_file_info.num_images];
// Each IntPtr array element will point to a copy of a
// string element in the openFileDialog.FileNames array.
for (int i = 0; i < openFileDialog.FileNames.Length; i++)
{
image_files_array[i] = Marshal.StringToCoTaskMemUni(openFileDialog.FileNames[i]);
}
// In order to obtain the address of the IntPtr array,
// we must fix it in memory. We do this using GCHandle.
GCHandle gch = GCHandle.Alloc(image_files_array, GCHandleType.Pinned);
// pimage_files will point to the head of the IntPtr array.
IntPtr pimage_files = gch.AddrOfPinnedObject();
// Set pimage_files as the value of the "image_files" field/
in_file_info.image_files = pimage_files;
// Call a Test API.
TestStructure(in_file_info);
// After the API is called, free the GCHandle.
gch.Free();
// Free each string contained in the IntPtr array.
for (int i = 0; i < openFileDialog.FileNames.Length; i++)
{
Marshal.FreeCoTaskMem(image_files_array[i]);
}
}

Related

how to marshal to an Array of objects - C#

I am kind of confused by Marshal and C#. I don't understand how to make a code change to marshal to an Array of Class. This is what my current code looks like.
IntPtr pBarcodesRaw = IntPtr.Zero;
retVal = LeadTools13Imports.L_BarCodeRead( handle, null, // null to scan whole image (uint)barcodeTypes,
LeadTools13Imports.BARCODE_SCANLINES_PER_PIXELS,LeadTools13Imports.BARCODE_MARKERS, 1, //this parameter control if read the first bar code or all the bar codes. 0= first and 1 = all.
_barcodeReaderParams,IntPtr.Zero,
null,
out pBarcodesRaw );
Lead tools is a third party library.
This use to only read the first bar code and stop which was marshalling to a single instance of BarCodeData. Now I have to read all the bar codes on a page.
if LeadTools13Imports.SUCCESS == retVal )
{ // extract the barcode read
barcodeData = (LeadTools13Imports.BARCODEDATA)Marshal.PtrToStructure(
pBarcodesRaw,
typeof( LeadTools13Imports.BARCODEDATA )
);
}
The bar code data class looks like this:
[StructLayout(LayoutKind.Sequential)]
internal class BARCODEDATA
{
internal Int32 nGroup = 0; // used only for CodeOne and PDF417
internal UInt32 ulType = 0;
internal Int32 nUnits = 0;
internal RECT rcBarLocation = new RECT();
internal Int32 nSizeofBarCodeData = 0;
[MarshalAs( UnmanagedType.LPStr )]
internal String pszBarCodeData = "";
internal Int32 nIndexDuplicate = 0; // for reading only
internal Int32 nTotalCount = 0; // for reading only
internal Int32 nDupCount = 0; // for reading only
}
I added this class
[StructLayout(LayoutKind.Sequential)]
internal class BarCodeArray
{
[MarshalAs(UnmanagedType.ByValArray , ArraySubType = UnmanagedType.Struct , SizeConst = 2)]
public BARCODEDATA[] _barcodes;
}
I am having a hard time understanding how do i change this line of code
barcodeData = (LeadTools13Imports.BARCODEDATA)Marshal.PtrToStructure(
pBarcodesRaw,
typeof( LeadTools13Imports.BARCODEDATA ) );
to marshal to an array of BARCODEDATA[]

Passing a complex Struct (with inner array of struct) from C# to C++

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.

How to programmatically set a custom icon on an Outlook search folder? (i.e. Outlook Folder SetCustomIcon)

I am attempting to use the Folder.SetCustomIcon() method to place a custom icon on a saved search folder I programmatically created. The SetCustomIcon() documentation is very sparse but can be found here for reference.
Also, the object it expects is here and again the examples are very sparse.
Would anybody know how to set the custom icon for a folder? The following is the code I have thus far:
searchFolders = inboxFolder.Store.GetSearchFolders();
foreach (Outlook.Folder folder in searchFolders)
{
if (folder.Name == "Expiring Retention Policy Mail")
{
folder.ShowItemCount = Microsoft.Office.Interop.Outlook.OlShowItemCount.olShowTotalItemCount;
folder.SetCustomIcon(new Bitmap(32, 32)); // <=-- this isn't working because it's expecting stdPicture which has very sparse information on how to convert to this type.
Globals.ThisAddIn.Application.ActiveExplorer().CurrentFolder = folder;
}
}
You just need to use a PictureDispConverter to go from an image/icon to IPictureDisp. Below is an example from MSDN. This only works in Outlook 2010+. To view custom Folder Icons in Outlook 2013, you need to view the Folder List - not the Mail view.
SetCustomIcon from MAPIFolder
private static void SetCustomIcon(Outlook.MAPIFolder folder)
{
Icon icon = null;
try
{
icon = Properties.Resources.myCustomIcon_16x16;
stdole.StdPicture iconPictureDisp = PictureDispConverter.ToIPictureDisp(icon) as stdole.StdPicture;
folder.SetCustomIcon(iconPictureDisp);
}
finally
{
icon.Dispose();
}
}
PictureDispConverter (Icon->IPictureDisp, Image->IPictureDisp)
public static class PictureDispConverter
{
//IPictureDisp GUID.
public static Guid iPictureDispGuid = typeof(stdole.IPictureDisp).GUID;
// Converts an Icon into an IPictureDisp.
public static stdole.IPictureDisp ToIPictureDisp(Icon icon)
{
PICTDESC.Icon pictIcon = new PICTDESC.Icon(icon);
return PictureDispConverter.OleCreatePictureIndirect(pictIcon, ref iPictureDispGuid, true);
}
// Converts an image into an IPictureDisp.
public static stdole.IPictureDisp ToIPictureDisp(Image image)
{
Bitmap bitmap = (image is Bitmap) ? (Bitmap)image : new Bitmap(image);
PICTDESC.Bitmap pictBit = new PICTDESC.Bitmap(bitmap);
return PictureDispConverter.OleCreatePictureIndirect(pictBit, ref iPictureDispGuid, true);
}
[DllImport("OleAut32.dll", EntryPoint = "OleCreatePictureIndirect", ExactSpelling = true,
PreserveSig = false)]
private static extern stdole.IPictureDisp OleCreatePictureIndirect(
[MarshalAs(UnmanagedType.AsAny)] object picdesc, ref Guid iid, bool fOwn);
private readonly static HandleCollector handleCollector =
new HandleCollector("Icon handles", 1000);
// WINFORMS COMMENT:
// PICTDESC is a union in native, so we'll just
// define different ones for the different types
// the "unused" fields are there to make it the right
// size, since the struct in native is as big as the biggest
// union.
private static class PICTDESC
{
//Picture Types
public const short PICTYPE_UNINITIALIZED = -1;
public const short PICTYPE_NONE = 0;
public const short PICTYPE_BITMAP = 1;
public const short PICTYPE_METAFILE = 2;
public const short PICTYPE_ICON = 3;
public const short PICTYPE_ENHMETAFILE = 4;
[StructLayout(LayoutKind.Sequential)]
public class Icon
{
internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Icon));
internal int picType = PICTDESC.PICTYPE_ICON;
internal IntPtr hicon = IntPtr.Zero;
internal int unused1 = 0;
internal int unused2 = 0;
internal Icon(System.Drawing.Icon icon)
{
this.hicon = icon.ToBitmap().GetHicon();
}
}
[StructLayout(LayoutKind.Sequential)]
public class Bitmap
{
internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Bitmap));
internal int picType = PICTDESC.PICTYPE_BITMAP;
internal IntPtr hbitmap = IntPtr.Zero;
internal IntPtr hpal = IntPtr.Zero;
internal int unused = 0;
internal Bitmap(System.Drawing.Bitmap bitmap)
{
this.hbitmap = bitmap.GetHbitmap();
}
}
}
}
here is simple version if you want to realize it in VBA
Sub Change_mapiRootFolder_Icon()
Dim mapiRootFolder As Outlook.MAPIFolder, mapiCurrFolder As Outlook.MAPIFolder
Dim stFullFolderPath As String, stCurrItemType As String, stIconPath As String, stCurrFolder As String
Dim i As Integer
Dim ipdMyPic As IPictureDisp
Set mapiCurrFolder = Application.ActiveExplorer.CurrentFolder
stCurrItemType = Application.ActiveExplorer.CurrentFolder.DefaultMessageClass
If stCurrItemType = "IPM.Note" Then 'mail Item types https://msdn.microsoft.com/en-us/library/office/ff861573.aspx
Set mapiRootFolder = mapiCurrFolder
stFullFolderPath = mapiRootFolder.Name
Do Until mapiRootFolder.Parent = "Mapi"
Set mapiRootFolder = mapiRootFolder.Parent
stFullFolderPath = mapiRootFolder.Name & "\" & stFullFolderPath
Loop
Debug.Print stFullFolderPath
stIconPath = "U:\OUTLOOK\Icons\Sent\iconarchive_sent1.ico"
stIconPath = "C:\Temp\iconarchive_sent1.bmp"
Set ipdMyPic = LoadPicture(stIconPath)
If Not (mapiCurrFolder Is Nothing) Then
mapiCurrFolder.SetCustomIcon ipdMyPic
End If
End If
End Sub

AccessViolation

I keep getting an AccessViolationException when calling the following from an external C DLL:
short get_device_list(char ***device_list, int *number_of_devices);
I set up a DLLImport declaration as such:
[DLLImport("mydll.dll")]
static public extern short get_device_list([MarshalAs(UnmanagedType.LPArray)] ref string[] devices, ref int number_of_devices);
My C# application code:
{
string[] devices = new string[20];
int i = 0;
short ret = 0;
ret = get_device_list(ref devices, ref i); // I receive the AccessViolation Exception here
// devices[0] = "2255f796e958f7f31a7d2e6b833d2d426c634621" which is correct.
}
Although I receive the exception, the device array gets filled correctly with the 2 UUIDs of the devices connected (and also gets resized to size = 2; i is also 2;).
What is wrong?
PS: After a long research I also tried:
[DLLImport("mydll.dll")]
static public extern short get_device_list(ref IntPtr devices, ref int number_of_devices);
and
{
IntPtr devices = new IntPtr();
int i = 0;
short ret = 0;
ret = get_device_list(ref devices, ref i); // No AccessViolation Exception here
string b = Marshal.PtrToStringAuto(devices); // b = "歀ׄ", which is incorrect
}
but that did not help me.
Thanks in advance!
[DLLImport("mydll.dll")]
static public extern short get_device_list(out IntPtr devices,
out int number_of_devices);
Is the best way to tackle this. The memory is allocated and owned on the native side of the interface. The trick is how to get at it. Something like this should work.
static public string[] getDevices()
{
IntPtr devices;
int deviceCount;
short ret = get_device_list(out devices, out deviceCount);
//need to test ret in case of error
string[] result = new string[deviceCount];
for (int i=0; i<deviceCount; i++)
{
IntPtr ptr = (IntPtr)Marshal.PtrToStructure(devices, typeof(IntPtr));
result[i] = Marshal.PtrToStringAnsi(ptr);
devices += IntPtr.Size;//move to next element of array
}
return result;
}
Your code was using PtrToStringAuto but that's going to interpret the data as UTF-16 encoded. But your C++ code uses char* which is 8 bit ANSI. So you need PtrToStringAnsi. OK, there's an assumption here that the encoding is not UTF-8, but that's a detail I cannot provide. It's easy enough to adapt this to UTF-8.
You should also double check that the native code uses the stdcall calling convention and isn't using cdecl.
Edit:
Ok I think I know the problem in your second attempt.
{
IntPtr devices = new IntPtr();
int i = 0;
short ret = 0;
ret = get_device_list(ref devices, ref i); // No AccessViolation Exception here
string b = Marshal.PtrToStringAuto(devices); // b = "歀ׄ", which is incorrect
}
You try to convert a pointer to an array of strings to a string. You have to deference it first. Please check whether this works for you:
IntPtr devices = new IntPtr();
int numDevices = 0;
short ret = get_device_list(ref devices, ref numDevices); // No AccessViolation Exception here
for (int i=0; i<numDevices; i++)
{
IntPtr ptrToString = Marshal.ReadIntPtr(devices);
string deviceString = Marshal.PtrToStringAnsi(ptrToString);
devices += IntPtr.size;
Console.WriteLine(deviceString);
}

Pinvoke C# from C++ dll using DLLimport in C#

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.

Categories

Resources