Demonstrates how to add a native string (char *) to a database and how to marshal a
Example
In this example, the class DatabaseClass is created to interact with an ADO.NET #pragma managed
directive preceding the class declaration. For more information on this directive, see
Note the private member of the DatabaseClass class: gcroot<DataTable ^> table
. Since native types cannot contain managed types, the gcroot keyword is necessary. For more information on gcroot, see How to: Declare Handles in Native Types.
The rest of the code in this example is native C++ code, as is indicated by the #pragma unmanaged
directive preceding main
. In this example, we are creating a new instance of DatabaseClass and calling its methods to create a table and populate some rows in the table. Note that native C++ strings are being passed as values for the database column StringCol. Inside DatabaseClass, these strings are marshaled to managed strings using the marshaling functionality found in the
Note |
---|
The memory allocated by StringToHGlobalAnsi must be deallocated by calling either |
В | Copy Code |
---|---|
// adonet_marshal_string_native.cpp // compile with: /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll #include <comdef.h> #include <gcroot.h> #include <iostream> using namespace std; #using <System.Data.dll> using namespace System; using namespace System::Data; using namespace System::Runtime::InteropServices; #define MAXCOLS 100 #pragma managed class DatabaseClass { public: DatabaseClass() : table(nullptr) { } void AddRow(char *stringColValue) { // Add a row to the table. DataRow ^row = table->NewRow(); row["StringCol"] = Marshal::PtrToStringAnsi( (IntPtr)stringColValue); table->Rows->Add(row); } void CreateAndPopulateTable() { // Create a simple DataTable. table = gcnew DataTable("SampleTable"); // Add a column of type String to the table. DataColumn ^column1 = gcnew DataColumn("StringCol", Type::GetType("System.String")); table->Columns->Add(column1); } int GetValuesForColumn(char *dataColumn, char **values, int valuesLength) { // Marshal the name of the column to a managed // String. String ^columnStr = Marshal::PtrToStringAnsi( (IntPtr)dataColumn); // Get all rows in the table. array<DataRow ^> ^rows = table->Select(); int len = rows->Length; len = (len > valuesLength) ? valuesLength : len; for (int i = 0; i < len; i++) { // Marshal each column value from a managed string // to a char *. values[i] = (char *)Marshal::StringToHGlobalAnsi( (String ^)rows[i][columnStr]).ToPointer(); } return len; } private: // Using gcroot, you can use a managed type in // a native class. gcroot<DataTable ^> table; }; #pragma unmanaged int main() { // Create a table and add a few rows to it. DatabaseClass *db = new DatabaseClass(); db->CreateAndPopulateTable(); db->AddRow("This is string 1."); db->AddRow("This is string 2."); // Now retrieve the rows and display their contents. char *values[MAXCOLS]; int len = db->GetValuesForColumn( "StringCol", values, MAXCOLS); for (int i = 0; i < len; i++) { cout << "StringCol: " << values[i] << endl; // Deallocate the memory allocated using // Marshal::StringToHGlobalAnsi. GlobalFree(values[i]); } delete db; return 0; } |
Output
В | |
---|---|
StringCol: This is string 1. StringCol: This is string 2. |
Compiling the Code
-
To compile the code from the command line, save the code example in a file named adonet_marshal_string_native.cpp and enter the following statement:
В Copy Code cl /clr /FU System.dll /FU System.Data.dll /FU System.Xml.dll adonet_marshal_string_native.cpp
Security
For information on security issues involving ADO.NET, see
See Also
Reference
Other Resources
Data Access Using ADO.NET in C++Native and .NET Interoperability