与非托管 SQLite 混合的 C++/CLI 代码
我尝试使用 C++/CLI 的混合模式来操作 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”的二进制文件和“数据文件”复制到 Win7,效果非常好!
在 Windows XP 上,我尝试了很多修改,但没有任何好处,但我现在的要点是:
我的项目有 OpenFileDialog
对象,该对象由不同的按钮 Button1
调用从调用上面所示代码的按钮 Button2
中。奇怪的是,当我点击 Button1
然后点击 Button2
时,SQLite 的代码什么也不做,而如果我在 Button2
之前点击 < code>Button1 代码工作正常!这仅适用于目标系统 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);
}
这里的任何人都可以看到问题!
I tried to use Mixed Mode
of C++/CLI to manipulate with SQLite. I wrote this code:
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);
This code tries to write to the file TTest
into the table Norm1Tab
which has six columns, however it fails to write any thing!! Any idea can help to fix the problem?
Edit:
I noticed something strange to me, actually I did compile the previous code on Windows XP SP3
machine and it showed the problem described. But when I compile it on Windows 7
machine it works fine without doing any modification! Also I tried to compile it on XP machine and then copy the binary file with 'sqlite3.dll' and the 'data file' to Win7 and it worked very well!
On Windows XP I had tried a lot of modifications without any benefit, but I am now with this gist:
My project has OpenFileDialog
object which is called by a button Button1
that differs from the button Button2
that calles the code shown above. The strange thing is that when I click on Button1
then click on Button2
the code of SQLite do nothing, while if I click on Button2
before Button1
the code works fine! This is only on Windows XP which is the targeted system.
Here is the code of Button1
handler:
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);
}
Any one here can see the problem!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可能的问题:
您检查文件是否正确打开?您的表只有六列吗?表已经创建了吗?表的类型是否正确(即文本,如果需要)?
在button1代码的末尾有一行
You use maskedTextBox7->Text for the sql query。
该字符串与表(第一列)中的正确值兼容吗?
Possible problems:
Did you check that the file was opened properly? Does your table have only six columns? Is the table created already? Are the types of the table, the correct ones (i.e TEXT if needed)?
At the end of the code of button1 you have the line
You use maskedTextBox7->Text for the sql query.
Is this String compatible with the proper value in the table (the first column)?