65.9K
CodeProject is changing. Read more.
Home

An OLE-DB DLL that you can use in ANSI-C

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

Feb 19, 2002

viewsIcon

75905

downloadIcon

750

An OLE-DB DLL that you can use in ANSI-C

Introduction

I program with a ansi-c compile tools named Labwindows/CVI. My OS is Windows 2k advance server. Everyone know that ANSI-C can not use OLE-DB but the Win2k OS support it. So I think I can let the CVI support the OLE-DB through DLL file. And finally I succeeded and here is how.

Details

First Use Wizard Create a MFC DLL project. And then update the stdafx.h file.

 #define VC_EXTRALEAN    // Exclude rarely-used stuff
                          // from Windows headers
   #include <AFXWIN.H>         // MFC core and standard components
   #include <AFXEXT.H>         // MFC extensions
   #include <AFXCVIEW.H>
   #include <AFXDISP.H>        // MFC Automation classes
   #include <AFXDTCTL.H>    // MFC support for Internet Explorer 
                           // 4 Common Controls

   #import "c:\program files\common files\system\ado\msado15.dll" \
     no_namespace \
    rename ("EOF", "adoEOF")

The last statement can let the project support the ADO ole-db version 2. The class cTestCpp (sorry , I made a test name for this project) does the main work and the testDll.c does the interface work.

Code Listings

class cTestCpp  
{
public:
  int Execute(const char *sql,int *AffectedRecord);
  int CloseRst(void);
  int CloseConn(void);
  BOOL IsBof(void);
  BOOL IsEof(void);
  int GetCount(int *iResult);
  int MoveLast(void);
  int MoveFirst(void);
  int MovePrevious(void);
  int Movenext(void);
  int openConn(const char *connStr);
  void test(void);
  int DBConnect(const char *strConn);
  int CreateRst(void);
  int openRst(const char *sql);
  int getCol(const char *colName,int dataType,char *result);

  cTestCpp();           //Construction 
  virtual ~cTestCpp();  //Destruction
private:
  _ConnectionPtr m_pConnection;    //The Ole-DB Connection 
  _RecordsetPtr pRecordSet;   //The RecordSet that contain the record

};

 
 // cTestCpp.cpp: implementation of the cTestCpp class.
//
////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "cTestCpp.h"

//#include "msado15.h"
//////////////////////////////////////////////////////////////////////

// Construction/Destruction
//////////////////////////////////////////////////////////////////////
cTestCpp::cTestCpp(){
  
  if (!AfxOleInit())
  {
    AfxMessageBox("ole Init Error");
    return ;
  }
  CoInitialize(NULL);
}
int cTestCpp::DBConnect(const char *strConn)
{
  return 0;
}

cTestCpp::~cTestCpp()
{
  CoUninitialize();
}


int cTestCpp::openConn(const char *connStr)
{
  try{
    HRESULT hr;
    hr = m_pConnection.CreateInstance( __uuidof( Connection ) );
    if (SUCCEEDED(hr)){
      hr = m_pConnection->Open(
      _bstr_t(connStr),
      _bstr_t(L""),
      _bstr_t(L""),
      adModeUnknown);
      
      return 0;
    }
  }
  catch (...) {
    return -1;
  }
  return -1;
}

int cTestCpp::CreateRst()
{
  HRESULT hr;
  hr=pRecordSet.CreateInstance( __uuidof(Recordset));
  if(SUCCEEDED(hr)){
    return 0;
  }
  pRecordSet->Release();  
  return -1;
}

int cTestCpp::openRst(const char *sql)
{
  _variant_t vRecsAffected(0L);
  _bstr_t bstrQuery(sql);
  HRESULT hr;
   _variant_t vNull;
  
  vNull.vt = VT_ERROR;
       vNull.scode = DISP_E_PARAMNOTFOUND;

  try{
    hr = pRecordSet.CreateInstance(__uuidof(Recordset));
      if (SUCCEEDED(hr))
      {
        pRecordSet->PutRefActiveConnection(m_pConnection);
        hr = pRecordSet->Open(_variant_t(bstrQuery), vNull,
          adOpenForwardOnly, adLockOptimistic, adCmdText);

    }
    
  }
  catch(...){
    return -1;
  }
  return 0;
}

int cTestCpp::getCol(const char *colName,int dataType,char *result)
{
  try{
    _variant_t  ss;
    CString s;
    ss = pRecordSet->GetCollect(colName);
    switch(dataType) {
    case INTEGER_TYPE:
      s.Format("%d",ss.intVal);
      break;
    case STRING_TYPE:
      s=CString(ss.bstrVal);
      break;
    case DOUBLE_TYPE:
      s.Format("%f",ss.dblVal);
      break;
    case DATE_TYPE:
      s.Format("%s",ss.date);
    default:
      s="error data type";
    }
    
    strcpy(result,(const char*)s);
  }
  catch(...){
    return -1;
  }
    return 0;
}

int cTestCpp::Movenext()
{
  try{
    pRecordSet->MoveNext();
  }
  catch(...){
    return -1;
  }
  return 0;
}

int cTestCpp::MovePrevious()
{
  try{
    pRecordSet->MovePrevious();
  }
  catch(...){
    return -1;
  }
  return 0;
}

int cTestCpp::MoveFirst()
{
  try{
    pRecordSet->MoveFirst();
  }
  catch(...){
    return -1;
  }
  return 0;
}

int cTestCpp::MoveLast()
{
  try{
    pRecordSet->MoveLast();
  }
  catch (...) {
    return -1;
  }
  return 0;
}

int cTestCpp::GetCount(int *iResult)
{
  try{
    *iResult=pRecordSet->GetRecordCount();
  }
  catch (...) {
    return -1;
  }
  return 0;
}
BOOL cTestCpp::IsEof(void){
  VARIANT_BOOL bl;
  try{
    bl=pRecordSet->GetadoEOF();  
  }
  catch (...) {
    return FALSE;
  }
  return bl;
}

BOOL cTestCpp::IsBof()
{
  VARIANT_BOOL bl;
  try{
    bl=pRecordSet->GetBOF();  
  }
  catch (...) {
    return FALSE;
  }
  return bl;
  
}

int cTestCpp::CloseConn()
{
  HRESULT hr;
  try{
      hr=m_pConnection->Close();
      m_pConnection.Release();
      if(!SUCCEEDED(hr)){
      return -1;
    }
  }
  catch (...) {
    return -1;
  }
  return 0;
}


int cTestCpp::CloseRst()
{
  HRESULT hr;
  try{
    hr =  pRecordSet->Close();  
    pRecordSet.Release();
    if(!SUCCEEDED(hr)){
      return -1;
    }
  }
  catch (...) {
    return -1;
  }
  return 0;
}

int cTestCpp::Execute(const char *sql, int *AffectedRecord)
{
  _variant_t vRecsAffected(0L);
  _bstr_t bstrQuery(sql);
  try{
    m_pConnection->Execute(bstrQuery, &vRecsAffected,
      adOptionUnspecified);
  }
  catch (...) {
    return -1;
  }
  *AffectedRecord=vRecsAffected.intVal;
  return 0;
}

And the interface code.

// testDll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "testDll.h"
#include "cTestCpp.h"

int openConn(const char *connstr){
  return   test.openConn(connstr);
}
int CreateRst(void){
  return test.CreateRst();
}
int openRst(const char *sql){
  return test.openRst(sql);
}

int getCol(const char *colName,int dataType,char *result){
  return test.getCol(colName,dataType,result);
}  
int movenext(){
  return test.Movenext();
}
int movePrevious(){
  return test.MovePrevious();
}
int moveFirst(){
  return test.MoveFirst();
}
int moveLast(){
  return test.Movenext();
}
int GetCount(int *iResult){
  return test.GetCount(iResult);
}
BOOL IsEof(){
  return test.IsEof();
}
BOOL IsBof(){
  return test.IsBof();
}
int closeConn(){
  return test.CloseConn();
}
int closeRst(){
  return test.CloseRst();
}
int Execute(const char *sql, int *AffectedRecord){
  return test.Execute(sql,AffectedRecord);
}

In the interface code all parameter is the const char*, because the ansi code can not support CString class etc. At last, we update the testDll.def file to export the function.