public void StorageCreateRecord(gamespySake.SAKECreateRecordInput input) { SAKEStartRequestResult startRequestResult; // Convert this pointer to IntPtr. This is needed for marshalling between C# and gamespy.dll GCHandle hUserData = GCHandle.Alloc(this, GCHandleType.Normal); IntPtr userData = GCHandle.ToIntPtr(hUserData); IntPtr pInput = Marshal.AllocHGlobal(Marshal.SizeOf(input)); Marshal.StructureToPtr(input, pInput, false); IntPtr request = gamespySake.sakeCreateRecord(sake, pInput, createRecordCallback, userData); if (request == IntPtr.Zero) { startRequestResult = gamespySake.sakeGetStartRequestResult(sake); Console.WriteLine("FAILURE: CreateRecord {0} ", startRequestResult); } else { WaitForResponse(); // retrieve the response Console.WriteLine("CreateRecord completed"); } hUserData.Free(); }
public void Run() { string gamename = "gmtest"; #if GSI_COMMON_DEBUG gamespyCommonDebug.gsOpenDebugFile("Debug_Sake.log"); gamespyCommonDebug.gsSetDebugLevel(GSIDebugCategory.GSIDebugCat_All, GSIDebugType.GSIDebugType_All, GSIDebugLevel.Hardcore); #endif Console.WriteLine("\n------------ SAKE C# sample ------------------------\n"); if (CheckServices(gamename) != GSIACResult.GSIACAvailable) { Console.WriteLine("{0}: Online services are unavailable now.", gamename); return; } if (Initialize()) { Console.WriteLine("{0}: Initialized.\n", gamename); } else { Terminate(); Console.WriteLine("\n------------ SAKE C# Sample Terminated with Failure ------------------------\n"); Console.WriteLine("Press AnyKey Continue...."); Console.ReadLine(); return; } // sakeGetRecordCount example Console.WriteLine("---------- {0} table : GetRecordCount \n", _tableId); StorageGetRecordCount(_tableId, null, true); // sakeGetMyRecords example Console.WriteLine("--------- {0} table : GetMyRecords\n", _tableId); // Initialize sample data System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); string[] fields = new string[12] { "recordid", "ownerid", "MyByte", "MyShort", "MyInt", "MyFloat", "MyAsciiString", "MyUnicodeString", "MyBoolean", "MyDateAndTime", "MyBinaryData", "MyFileID" }; //gamespySake.SAKEGetMyRecordsInput getMyRecordsInput = new gamespySake.SAKEGetMyRecordsInput(); getMyRecordsInput.mTableId = _tableId; getMyRecordsInput.mNumFields = 12; getMyRecordsInput.mFieldNames = Marshal.AllocHGlobal(getMyRecordsInput.mNumFields * Marshal.SizeOf(typeof(IntPtr))); IntPtr[] pFieldNames = new IntPtr[getMyRecordsInput.mNumFields]; for (int i = 0; i < getMyRecordsInput.mNumFields; i++) { pFieldNames[i] = Marshal.StringToHGlobalAnsi(fields[i]); } Marshal.Copy(pFieldNames, 0, getMyRecordsInput.mFieldNames, getMyRecordsInput.mNumFields); GCHandle hInput = GCHandle.Alloc(getMyRecordsInput); StorageGetMyRecords(getMyRecordsInput); hInput.Free(); // // sakeCreateRecord example Console.WriteLine("--------- {0} table : CreateRecord\n", _tableId); gamespySake.SAKECreateRecordInput createRecordInput = new gamespySake.SAKECreateRecordInput(); gamespySake.SAKEField[] field = new gamespySake.SAKEField[9]; // ownerid, recordid and dateandtime is auto created, do not initialize them // Initialize the field[] array int j = 0; field[j].mName = "MyByte"; field[j].mType = SAKEFieldType.SAKEFieldType_BYTE; field[j].mValue.mByte = 1; j++; field[j].mName = "MyShort"; field[j].mType = SAKEFieldType.SAKEFieldType_SHORT; field[j].mValue.mShort = 2; j++; field[j].mName = "MyInt"; field[j].mType = SAKEFieldType.SAKEFieldType_INT; field[j].mValue.mInt = 3; j++; field[j].mName = "MyFloat"; field[j].mType = SAKEFieldType.SAKEFieldType_FLOAT; field[j].mValue.mFloat = 4.0F; j++; field[j].mName = "MyAsciiString"; field[j].mType = SAKEFieldType.SAKEFieldType_ASCII_STRING; field[j].mValue.mString = new IntPtr(); field[j].mValue.mString = Marshal.StringToHGlobalAnsi("ASCII string"); j++; field[j].mName = "MyUnicodeString"; field[j].mType = SAKEFieldType.SAKEFieldType_UNICODE_STRING; field[j].mValue.mString = new IntPtr(); field[j].mValue.mString = Marshal.StringToHGlobalUni("UNICODE string"); j++; field[j].mName = "MyBoolean"; field[j].mType = SAKEFieldType.SAKEFieldType_BOOLEAN; field[j].mValue.mBoolean = true; j++; field[j].mName = "MyBinaryData"; field[j].mType = SAKEFieldType.SAKEFieldType_BINARY_DATA; field[j].mValue.mBinaryData = new gamespySake.SAKEBinaryData(); field[j].mValue.mBinaryData.mLength = 10; field[j].mValue.mBinaryData.mValue = Marshal.AllocHGlobal(field[j].mValue.mBinaryData.mLength); byte[] binaryData = new byte[10] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Marshal.Copy(binaryData, 0, field[j].mValue.mBinaryData.mValue, binaryData.Length); j++; field[j].mName = "MyFileID"; field[j].mType = SAKEFieldType.SAKEFieldType_INT; field[j].mValue.mInt = 55555; //Correct way of Marshaling SAKEField array into IntPtr createRecordInput.mTableId = _tableId; createRecordInput.mNumFields = field.Length; // number of elements in the field[] array. // Sake expects all the fields in a continous block of memory. createRecordInput.mFields = Marshal.AllocHGlobal(createRecordInput.mNumFields * Marshal.SizeOf(typeof(gamespySake.SAKEField))); for (int i = 0; i < createRecordInput.mNumFields; i++) { // Obtain the pointer to the specific element in the Unmanaged Memory IntPtr pField = new IntPtr(createRecordInput.mFields.ToInt32() + i * Marshal.SizeOf(typeof(gamespySake.SAKEField))); //Marshal filed[i] to Unmanaged memory Marshal.StructureToPtr(field[i], pField, false); // must delete field[] after the callback returns } // Want to make sure createRecordInput does not get garbage collected. GCHandle hCreateInput = GCHandle.Alloc(createRecordInput); StorageCreateRecord(createRecordInput); hCreateInput.Free(); // Terminate(); Console.WriteLine("\n------------ SAKE C# Sample Completed------------------------\n"); Console.WriteLine("Press Enter Continue...."); Console.ReadLine(); }