Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / MFC
Article

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

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
3 Jul 2002 74.6K   738   24   7
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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
China China
I am a particulaly pragrammer in Coding.I began code in July,1997.My birthday is 7th,March 1977.I am familar in VC++,VB,.net and database.Of course,I always use asp,php to write webpage Unsure | :~ )

Comments and Discussions

 
GeneralGetCount() Pin
leonrom13-Nov-08 2:32
leonrom13-Nov-08 2:32 
Questioncan you rewrite the code without MFC ? Pin
Yescode12-Feb-04 16:01
Yescode12-Feb-04 16:01 
GeneralPlain C Pin
Anonymous22-Jul-03 7:53
Anonymous22-Jul-03 7:53 
GeneralRe: Plain C Pin
roboo22-Jul-03 22:54
roboo22-Jul-03 22:54 
Sure,you are right.But your program must include so many head file.
Anyway,you give me a fresh idea,thank you very much

I am I,Who is who,I am who,Who am I
QuestionHow can I embed the DLL with my ANSI-C program? Pin
Yuk Lun, Cheung23-Feb-03 15:25
Yuk Lun, Cheung23-Feb-03 15:25 
QuestionWhy not use MIDL code? Pin
Jörgen Sigvardsson20-Feb-02 10:54
Jörgen Sigvardsson20-Feb-02 10:54 
AnswerRe: Why not use MIDL code? Pin
roboo21-Feb-02 13:55
roboo21-Feb-02 13:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.