#include "test.h"
#include <iostream.h>
#include <comdef.h>
#include <atlbase.h>
#pragma warning(disable:4146)
#import "C:\Program Files\Common Files\System\ado\msado15.dll" named_guids rename("EOF","adoEOF"), rename("BOF","adoBOF")
#pragma warning(default:4146)
//using namespace ADODB;char gettime()
{
    _ConnectionPtr pConn("ADODB.Connection");
    _RecordsetPtr pRs("ADODB.Recordset");
    _CommandPtr pCommand;
    pCommand.CreateInstance(__uuidof(Command));
//    Cstring strConn;
    
    pConn->Open("Provider=SQLOLEDB;Server=10.163.10.3;DataBase=master;UID=trace;PWD=traceaeclmis","","",adModeUnknown);
    pConn->ConnectionTimeout=300;    pCommand->ActiveConnection=pConn;
    pCommand->CommandText="Select Convert(char(20),getdate(),120) AS sysTime";
    pCommand->CommandType=adCmdText;
    pCommand->CommandTimeout=300;
    pCommand->Parameters->Refresh();    pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
    _variant_t varValue=pRs->GetCollect("sysTime");
    Cstring strValue=(char*)_bstr_t(varValue);
    return strValue;
}以上代码是为了实现取SQL服务器时间,返回的一定要是字符串。我要封装在Win32 Dynamic-Link Library 里面供其他平台调用
大侠帮看看有什么问题,怎么这个函数无法调用到呢?
用VC++6.0 Depends 解析这个dll 没看到这个函数,肯定是有什么问题了。

解决方案 »

  1.   

    你封装的api,声明就是错误的,你应该返回字符串,而不是字符
      

  2.   

    最好可以帮我修改一下把工程文件发给我,非常感谢。
    我Mail: [email protected]
      

  3.   

    char gettime()改成extern "C" __stdcall char gettime()
      

  4.   

    你没有导出啊:
    extern "C" _declspec(dllexport) _stdcall char  gettime()
    {
    ...
    }
      

  5.   

    可能这样才是lz想要的
    extern "C" _declspec(dllexport) _stdcall char*  gettime() 

    ... 
    }
      

  6.   

    对,我貌似忘记加_declspec(dllexport)了
      

  7.   

    这个错误:

    e:\tddownload\test\debug\msado15.tlh(409) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
      

  8.   

    这个错误:
    E:\TDdownload\test\test.cpp(14) : warning C4518: 'char ' : storage-class or type specifier(s) unexpected here; ignored是要引入什么名字空间吧??
      

  9.   

    可能这样才是lz想要的 
    extern "C" _declspec(dllexport) _stdcall char*  gettime() 

    ... // LZ不会把这个三个也带进去了吧
      

  10.   

    认真看了一下,LZ的不是错误,是 warning ,11楼的错误是 引入ADO数据库那里出来的,不要紧.
    #12说的是 char ,不是char*,比较奇怪
      

  11.   

    DBTime.cpp
    DBTIME_API void GetTime(LPTSTR lpBuffer,int nBufferLength)
    {
        ::CoInitialize(NULL);
        _ConnectionPtr pConn;
        pConn.CreateInstance(__uuidof(Connection));
        _RecordsetPtr pRs;
        pRs.CreateInstance(__uuidof(Recordset));
        _CommandPtr pCommand;
        pCommand.CreateInstance(__uuidof(Command));    pConn->Open(_bstr_t("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;User ID=sa;Initial Catalog=test;Data Source=(local)"),"","",adModeUnknown);
        //pConn->ConnectionTimeout=(long)300;    pCommand->ActiveConnection=pConn;
        pCommand->CommandText=_bstr_t("Select Convert(varchar(20),getdate(),120) AS sysTime");
        pCommand->CommandType=adCmdText;
        //pCommand->CommandTimeout=(long)300;
        pCommand->Parameters->Refresh();    pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
        _variant_t varValue=pRs->GetCollect("sysTime");
        _bstr_t bstrValue=varValue.bstrVal;    LPTSTR pszDestText, pszDestEnd ;
        size_t cchRemaining = 0;
        StringCchPrintfEx(lpBuffer,
            nBufferLength,
            &pszDestEnd,
            &cchRemaining,
            STRSAFE_FILL_BEHIND_NULL,
            _T("%s"),
            (LPCTSTR)bstrValue
            );
        ::CoUninitialize();
        return;}DBTime.hDBTIME_API void GetTime(LPTSTR lpBuffer,int nBufferLength);调用DBTime.dll 中GetTime#include "..\DBTime\DBTime.h"
    #pragma comment(lib, "D:\\projects2008\\VCTrainning\\Debug\\DBTime.lib")DWORD DLLTesting()
    {
        TCHAR lpDBTime[100];
        ZeroMemory(lpDBTime, sizeof(TCHAR) * 100);
        GetTime(lpDBTime, 100);
        TRACE(_T("GetTime=%s\r\n"), lpDBTime);
        return 0;
    }
      

  12.   

    非常感谢所有热心人
    这个函数在vb里面调用的时候怎么搞?
    能不能改改,让这个函数没有参数,在vb 里面直接调用就完了,最多分配内存。
    我自己再试试吧。
      

  13.   


    编译出错:
    e:\tddownload\timeget\gettime\gettime.h(1) : error C2144: syntax error : missing ';' before type 'void'
    e:\tddownload\timeget\gettime\gettime.h(1) : error C2501: 'DBTIME_API' : missing storage-class or type specifiers
    e:\tddownload\timeget\gettime\gettime.h(1) : fatal error C1004: unexpected end of file found都指向你的头文件DBTime.h
      

  14.   


    好多Warning & Error:
    test.cpp
    e:\tddownload\test\test.h(1) : warning C4185: ignoring unknown #import attribute 'no_namespaces'
    e:\tddownload\test\debug\msado15.tlh(409) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
    E:\TDdownload\test\test.cpp(14) : warning C4518: 'char ' : storage-class or type specifier(s) unexpected here; ignored
    E:\TDdownload\test\test.cpp(14) : warning C4230: anachronism used : modifiers/qualifiers interspersed, qualifier ignored
    E:\TDdownload\test\test.cpp(15) : error C2165: 'left-side modifier' : cannot modify pointers to data
    E:\TDdownload\test\test.cpp(15) : error C2501: 'gettime' : missing storage-class or type specifiers
    E:\TDdownload\test\test.cpp(15) : error C2556: 'int *__cdecl gettime(void)' : overloaded function differs only by return type from 'char *__cdecl gettime(void)'
            e:\tddownload\test\test.h(4) : see declaration of 'gettime'
    E:\TDdownload\test\test.cpp(16) : error C2065: '_ConnectionPtr' : undeclared identifier
    E:\TDdownload\test\test.cpp(16) : error C2146: syntax error : missing ';' before identifier 'pConn'
    E:\TDdownload\test\test.cpp(16) : error C2065: 'pConn' : undeclared identifier
    E:\TDdownload\test\test.cpp(17) : error C2065: '_RecordsetPtr' : undeclared identifier
    E:\TDdownload\test\test.cpp(17) : error C2146: syntax error : missing ';' before identifier 'pRs'
    E:\TDdownload\test\test.cpp(17) : error C2065: 'pRs' : undeclared identifier
    E:\TDdownload\test\test.cpp(18) : error C2065: '_CommandPtr' : undeclared identifier
    E:\TDdownload\test\test.cpp(18) : error C2146: syntax error : missing ';' before identifier 'pCommand'
    E:\TDdownload\test\test.cpp(18) : error C2065: 'pCommand' : undeclared identifier
    E:\TDdownload\test\test.cpp(19) : error C2228: left of '.CreateInstance' must have class/struct/union type
    E:\TDdownload\test\test.cpp(19) : error C2065: 'Command' : undeclared identifier
    E:\TDdownload\test\test.cpp(22) : error C2227: left of '->Open' must point to class/struct/union
    E:\TDdownload\test\test.cpp(22) : error C2065: 'adModeUnknown' : undeclared identifier
    E:\TDdownload\test\test.cpp(24) : error C2227: left of '->ConnectionTimeout' must point to class/struct/union
    E:\TDdownload\test\test.cpp(26) : error C2227: left of '->ActiveConnection' must point to class/struct/union
    E:\TDdownload\test\test.cpp(27) : error C2227: left of '->CommandText' must point to class/struct/union
    E:\TDdownload\test\test.cpp(28) : error C2227: left of '->CommandType' must point to class/struct/union
    E:\TDdownload\test\test.cpp(28) : error C2065: 'adCmdText' : undeclared identifier
    E:\TDdownload\test\test.cpp(29) : error C2227: left of '->CommandTimeout' must point to class/struct/union
    E:\TDdownload\test\test.cpp(30) : error C2227: left of '->Parameters' must point to class/struct/union
    E:\TDdownload\test\test.cpp(30) : error C2227: left of '->Refresh' must point to class/struct/union
    E:\TDdownload\test\test.cpp(32) : error C2227: left of '->Execute' must point to class/struct/union
    E:\TDdownload\test\test.cpp(32) : error C2065: 'adCmdUnknown' : undeclared identifier
    E:\TDdownload\test\test.cpp(33) : error C2227: left of '->GetCollect' must point to class/struct/union
    E:\TDdownload\test\test.cpp(34) : error C2065: 'CString' : undeclared identifier
    E:\TDdownload\test\test.cpp(34) : error C2146: syntax error : missing ';' before identifier 'strValue'
    E:\TDdownload\test\test.cpp(34) : error C2065: 'strValue' : undeclared identifier
    E:\TDdownload\test\test.cpp(34) : error C2679: binary '=' : no operator defined which takes a right-hand operand of type 'class _bstr_t' (or there is no acceptable conversion)
    Ö´ÐРcl.exe Ê±³ö´í.test.dll - 1 error(s), 0 warning(s)
      

  15.   

    你要在VB中使用啊?
    改起来很容易,不过我建议你做成ATL组件形式
    如果改成COM(ATL)组件
    这样在VB中可以这样使用set tm = createobject("DBTimeLib.DBTime")
    str = tm.GetTime()
    msgbox str这就是VB的调用方式,而且适用性更好一些如果要从VB中调用普通的DLL,那么就是多几行代码就看你的要求了
      

  16.   

    还有,你的function,返回值类型是错的,即便可以通过build,也无法真正的使用
      

  17.   

    先说说你希望以一个普通dll,还是以个COM组件形式的dll,来封装这个GetTime()?
      

  18.   

     我想用VB6.0使用的,普通dll 应该好一些吧。
    如果有标准dll 的话就更好了,不论什么平台都可以使用。
      

  19.   

    不是这样的,你的dll,已经使用了ADO组件,还有ATL的内容,所以这个dll即便是以规范的方式封装,也依赖于windows平台。所以跨平台是没有意义的。而且你是vb使用,就更是如此了。即便你用java调用这个dll,也一样必须要有ADO组件的支持。我的dll是win32 project - DLL- support ATL 
    主要的源代码如下: 
    stdafx.h 
    C/C++ code
    // stdafx.h : include file for standard system include files,
    // or project specific include files that are used frequently, but
    // are changed infrequently
    //#pragma once#include "targetver.h"#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
    // Windows Header Files:
    #include <windows.h>
    #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // some CString constructors will be explicit#include <atlbase.h>
    #include <atlstr.h>// TODO: reference additional headers your program requires here
    #include <strsafe.h>
    #import "d:\program files\common files\system\ado\msado15.dll" no_namespace rename("EOF", "adoEOF") DBTime.h 
    C/C++ code
    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the DBTIME_EXPORTS
    // symbol defined on the command line. this symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // DBTIME_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef DBTIME_EXPORTS
    #define DBTIME_API __declspec(dllexport)
    #else
    #define DBTIME_API __declspec(dllimport)
    #endif// This class is exported from the DBTime.dll
    class DBTIME_API CDBTime {
    public:
        CDBTime(void);
        // TODO: add your methods here.
    };extern DBTIME_API int nDBTime;DBTIME_API int fnDBTime(void);DBTIME_API void GetTime(LPTSTR lpBuffer,int nBufferLength);
    DBTIME_API LPTSTR GetTimeEx();DBTime.cpp C/C++ code
    // DBTime.cpp : Defines the exported functions for the DLL application.
    //#include "stdafx.h"
    #include "DBTime.h"
    // This is an example of an exported variable
    DBTIME_API int nDBTime=0;// This is an example of an exported function.
    DBTIME_API int fnDBTime(void)
    {
        return 42;
    }// This is an example of an exported function.
    DBTIME_API void GetTime(LPTSTR lpBuffer,int nBufferLength)
    {
        ::CoInitialize(NULL);
        _ConnectionPtr pConn;
        pConn.CreateInstance(__uuidof(Connection));
        _RecordsetPtr pRs;
        pRs.CreateInstance(__uuidof(Recordset));
        _CommandPtr pCommand;
        pCommand.CreateInstance(__uuidof(Command));    pConn->Open(_bstr_t("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;User ID=sa;Initial Catalog=test;Data Source=(local)"),"","",adModeUnknown);
        //pConn->ConnectionTimeout=(long)300;    pCommand->ActiveConnection=pConn;
        pCommand->CommandText=_bstr_t("Select Convert(varchar(20),getdate(),120) AS sysTime");
        pCommand->CommandType=adCmdText;
        //pCommand->CommandTimeout=(long)300;
        pCommand->Parameters->Refresh();    pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
        _variant_t varValue=pRs->GetCollect("sysTime");
        _bstr_t bstrValue=varValue.bstrVal;    LPTSTR pszDestText, pszDestEnd ;
        size_t cchRemaining = 0;
        StringCchPrintfEx(lpBuffer,
            nBufferLength,
            &pszDestEnd,
            &cchRemaining,
            STRSAFE_FILL_BEHIND_NULL,
            _T("%s"),
            (LPCTSTR)bstrValue
            );
        ::CoUninitialize();
        return;}// This is an example of an exported function.
    DBTIME_API LPTSTR GetTimeEx()
    {
        ::CoInitialize(NULL);
        _ConnectionPtr pConn;
        pConn.CreateInstance(__uuidof(Connection));
        _RecordsetPtr pRs;
        pRs.CreateInstance(__uuidof(Recordset));
        _CommandPtr pCommand;
        pCommand.CreateInstance(__uuidof(Command));    pConn->Open(_bstr_t("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;User ID=sa;Initial Catalog=test;Data Source=(local)"),"","",adModeUnknown);
        //pConn->ConnectionTimeout=(long)300;    pCommand->ActiveConnection=pConn;
        pCommand->CommandText=_bstr_t("Select Convert(varchar(20),getdate(),120) AS sysTime");
        pCommand->CommandType=adCmdText;
        //pCommand->CommandTimeout=(long)300;
        pCommand->Parameters->Refresh();    pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
        _variant_t varValue=pRs->GetCollect("sysTime");
        _bstr_t bstrValue=varValue.bstrVal;    LPTSTR lpBuffer = new TCHAR[100];
        LPTSTR pszDestEnd ;
        size_t cchRemaining = 0;
        
        StringCchPrintfEx(lpBuffer,
            100,
            &pszDestEnd,
            &cchRemaining,
            STRSAFE_FILL_BEHIND_NULL,
            _T("%s"),
            (LPCTSTR)bstrValue
            );
        ::CoUninitialize();
        return lpBuffer;}
    // This is the constructor of a class that has been exported.
    // see DBTime.h for the class definition
    CDBTime::CDBTime()
    {
        return;
    }这个DLL里面有两个API,GetTime()和GetTimeEx(),生成的DLL名字为DBTime.dll,导出的声明都在DBTime.h中,调试的时候需要用到这个头文件 
      

  20.   

    VC调VB的东西,如果封装数据成VARIANT这样的形式,会比较好做一些
      

  21.   


    我不需要跨平台调用,都是windows,只是98 上用而已。
      

  22.   

    #include "targetver.h" 引用这个什么意思?我的引用不到。
      

  23.   

    windows 98?晕你用的是VC6, 2005 , 2008?
      

  24.   

    我用的是VC6。
    但是这个dll 做出来到时候是给98系统或者2000系统用的
    没什么关系吧?
      

  25.   

    原来我有写过一个返回Variant 的函数,发现在一个测试平台上面没法用,它只认识string型。
      

  26.   

    在解决这个问题之前,还是先明确几个问题第一,楼主需要一个dll,一个规则的dll
    第二,怎样在规则dll中实现返回字符串
    第三,这个dll是否能够为vb或者类似vb的应用开发环境所调用
    第四,怎样的字符串能被vb使用第二个问题是关键首先,楼主返回char,是错误的,因为这仅仅是一个单字节的字符,不是一个字符串。
    常规的函数或者API,返回字符串。有基本的两种第一个,是返回字符串的指针char *
    这种返回指针的方式,要考虑字符串的生命期范围的问题。所以没有经验的人,要谨慎使用第二个,是返回CString,或者string这样类对象。
    这个方式的好处是这些类对象内部可以维护内存释放的问题。比较省心,不好处是必须依赖MFC,或者STL。至于,其他BSTR,variant,暂时不讨论,因为我们的dll,不是com组件和接口。仅仅是API的封装。先写到这里,下回继续