与非托管 SQLite 混合的 C++/CLI 代码

发布于 2024-12-08 21:20:13 字数 4487 浏览 0 评论 0原文

我尝试使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笔落惊风雨 2024-12-15 21:20:13

可能的问题:

您检查文件是否正确打开?您的表只有六列吗?表已经创建了吗?表的类型是否正确(即文本,如果需要)?

在button1代码的末尾有一行

this->maskedTextBox7->Text=HexSig;

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

this->maskedTextBox7->Text=HexSig;

You use maskedTextBox7->Text for the sql query.
Is this String compatible with the proper value in the table (the first column)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文