【发布时间】:2011-12-03 08:24:31
【问题描述】:
我尝试使用 C++/CLI 的Mixed Mode 来操作 SQLite。我写了这段代码:
int rc;
char *sql, *Sig, *DocName, *OrgName,*From,*To,*Date;
sqlite3 *db; //Database handle
sqlite3_stmt *stmt; //used to handle stmt for step(), its is name prepared stmt
sql = "insert into Norm1Tab values (?,?,?,?,?,?);";
sqlite3_open("TTest", &db);
Sig =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox7->Text).ToPointer();
DocName =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox2->Text).ToPointer();
OrgName =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox3->Text).ToPointer();
From =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox4->Text).ToPointer();
To =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox5->Text).ToPointer();
Date =(char *)Marshal::StringToHGlobalAnsi(this->maskedTextBox6->Text).ToPointer();
rc= sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);//compile sql to byte code
sqlite3_bind_text(stmt, 1, Sig, strlen(Sig),SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, DocName, strlen(DocName),SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, OrgName, strlen(OrgName),SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, From, strlen(From),SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, To, strlen(To),SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, Date, strlen(Date),SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);//talk directly with VDBE and execute the bytecode
//free all handles and objects
Marshal::FreeHGlobal((IntPtr)Sig);
Marshal::FreeHGlobal((IntPtr)DocName);
Marshal::FreeHGlobal((IntPtr)OrgName);
Marshal::FreeHGlobal((IntPtr)From);
Marshal::FreeHGlobal((IntPtr)To);
Marshal::FreeHGlobal((IntPtr)Date);
sqlite3_finalize(stmt);
sqlite3_close(db);
此代码尝试将文件TTest 写入有六列的表Norm1Tab,但是它没有写入任何东西!!有什么想法可以帮助解决问题吗?
编辑:
我注意到一些奇怪的东西,实际上我确实在Windows XP SP3 机器上编译了之前的代码,它显示了所描述的问题。但是当我在Windows 7 机器上编译它时,它可以正常工作而无需进行任何修改!我也尝试在XP机器上编译它,然后将带有'sqlite3.dll'和'data file'的二进制文件复制到Win7,效果很好!
在 Windows XP 上,我尝试了很多修改但没有任何好处,但我现在有了这个要点:
我的项目有OpenFileDialog 对象,该对象由一个按钮Button1 调用,该对象与调用上述代码的按钮Button2 不同。奇怪的是,当我点击Button1 然后点击Button2 SQLite 的代码什么也不做,而如果我在Button1 之前点击Button2 代码工作正常!这仅适用于作为目标系统的 Windows XP。
这里是Button1处理程序的代码:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
if(openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
this->maskedTextBox1->Text=openFileDialog1->FileName->ToString();
}
HANDLE hFile;
HANDLE hMap;
//open the file//
hFile = ::CreateFile((LPCWSTR)Marshal::StringToHGlobalUni(this->maskedTextBox1->Text).ToPointer(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
0,OPEN_EXISTING , FILE_FLAG_SEQUENTIAL_SCAN, 0);
//get the size for creating the signature and mapping it to Virtual mem//
unsigned long sifi=0;
if(hFile !=INVALID_HANDLE_VALUE){
hMap= ::CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0);//create Mem mapping for the file in virtual memory
sifi= ::GetFileSize(hFile,NULL);
}
//load the binary form of the file to memory//
LPVOID base;
BYTE b1,b2,b3,b4,b5,b6,b7,b8,b9,b10;
int inc=2;
if( hMap!=NULL){
base = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);//load the mapped file into the RAM
b1= *((BYTE *)base + sifi/inc++);
b2= *((BYTE *)base + sifi/inc++);
b3= *((BYTE *)base + sifi/inc++);
b4= *((BYTE *)base + sifi/inc++);
b5= *((BYTE *)base + sifi/inc++);
b6= *((BYTE *)base + sifi/inc++);
b7= *((BYTE *)base + sifi/inc++);
b8= *((BYTE *)base + sifi/inc++);
b9= *((BYTE *)base + sifi/inc++);
b10= *((BYTE *)base + sifi/inc++);
}
inc=2;
//show the sig
String^ HexSig;
HexSig = String::Format("{0:X2}", b1)+String::Format("{0:X2}", b2)+String::Format("{0:X2}", b3)+String::Format("{0:X2}", b4)+String::Format("{0:X2}", b5)+String::Format("{0:X2}", b6)+String::Format("{0:X2}", b7)+String::Format("{0:X2}", b8)+String::Format("{0:X2}", b9)+String::Format("{0:X2}", b10);
this->maskedTextBox7->Text=HexSig;
//free handles
::CloseHandle(hFile);
::CloseHandle(hMap);
::UnmapViewOfFile(base);
}
这里的任何人都可以看到问题!
【问题讨论】:
-
你为什么在 C++/CLI 中使用
Marshal::FreeHGlobal,而你可以直接调用GlobalFree? -
@Ben :
Marshal::FreeHGlobal公开了LocalFree函数,而不是GlobalFree,但你的观点仍然成立。 -
@BenVoigt:因为我使用了
Marshal::StringToHGlobalAnsi!我不确定我是否理解你! -
@ildjarn:那么它是有史以来命名最差的函数。
-
@Ben:我不会在那里争论......
标签: c++ winapi visual-c++ sqlite c++-cli