0

I seem to be having a problem. I'm trying to get a c++ function to be used in c code.

I tried these methods

If i need to get rid of the class altogether then i will ,but i don't want to lose the download feed to the console.

Here is the code that works in c++ but not in c.

#include <tchar.h>
#include <urlmon.h>
#pragma comment(lib,"urlmon.lib")
#include <stdio.h>

class MyCallback : public IBindStatusCallback
{
public:
    MyCallback() {}

    ~MyCallback() { }

    // This one is called by URLDownloadToFile
    STDMETHOD(OnProgress)(/* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR wszStatusText)
    {
        printf("Downloaded %i of %i byte(s) Status Code = %i\n",ulProgress, ulProgressMax, ulStatusCode);
        return S_OK;
    }

    // The rest  don't do anything...
    STDMETHOD(OnStartBinding)(/* [in] */ DWORD dwReserved, /* [in] */ IBinding __RPC_FAR *pib)
    { return E_NOTIMPL; }

    STDMETHOD(GetPriority)(/* [out] */ LONG __RPC_FAR *pnPriority)
    { return E_NOTIMPL; }

    STDMETHOD(OnLowResource)(/* [in] */ DWORD reserved)
    { return E_NOTIMPL; }

    STDMETHOD(OnStopBinding)(/* [in] */ HRESULT hresult, /* [unique][in] */ LPCWSTR szError)
    { return E_NOTIMPL; }

    STDMETHOD(GetBindInfo)(/* [out] */ DWORD __RPC_FAR *grfBINDF, /* [unique][out][in] */ BINDINFO __RPC_FAR *pbindinfo)
    { return E_NOTIMPL; }

    STDMETHOD(OnDataAvailable)(/* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC __RPC_FAR *pformatetc, /* [in] */ STGMEDIUM __RPC_FAR *pstgmed)
    { return E_NOTIMPL; }

    STDMETHOD(OnObjectAvailable)(/* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown __RPC_FAR *punk)
    { return E_NOTIMPL; }

    // IUnknown stuff
    STDMETHOD_(ULONG,AddRef)()
    { return 0; }

    STDMETHOD_(ULONG,Release)()
    { return 0; }

    STDMETHOD(QueryInterface)(/* [in] */ REFIID riid, /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
    { return E_NOTIMPL; }
};

int main()
{
    MyCallback pCallback;
    HRESULT url = URLDownloadToFile(NULL,_T("https://dl.dropboxusercontent.com/u/102222417/jediAcademy.zip"),_T("C:\\JKA\\file.zip"),0,&pCallback);

    if(url == S_OK)
    {
        printf("Successful!");
        getchar();
    }

    else if(url == E_OUTOFMEMORY)
    {
        printf("Not enough memory!");
    }

    else if (url == INET_E_DOWNLOAD_FAILURE)
    {
        printf("ERROR: INET invalid resource");
    }
    return 0;
}

when running in C code it gives this error

1>------ Build started: Project: Downloader++, Configuration: Debug
Win32 ------ 2012\projects\downloader++\downloader++\main.c(101):
error C2061: syntax error : identifier 'MyCallback'
2012\projects\downloader++\downloader++\main.c(101): error C2059:
syntax error : ';'
2012\projects\downloader++\downloader++\main.c(101): error C2059:
syntax error : ':'
2012\projects\downloader++\downloader++\main.c(150): error C2065:
'MyCallback' : undeclared identifier
2012\projects\downloader++\downloader++\main.c(150): error C2146:
syntax error : missing ';' before identifier 'pCallback'
2012\projects\downloader++\downloader++\main.c(150): error C2065:
'pCallback' : undeclared identifier 1>
studio 2012\projects\downloader++\downloader++\main.c(151): error
C2275: 'HRESULT' : illegal use of this type as an expression 1>       
c:\program files (x86)\windows kits\8.0\include\um\winnt.h(556) : see
declaration of 'HRESULT'
2012\projects\downloader++\downloader++\main.c(151): error C2146:
syntax error : missing ';' before identifier 'url'
1>c:\users\gamer\documents\visual studio
2012\projects\downloader++\downloader++\main.c(151): error C2065:
'url' : undeclared identifier 1>c:\users\gamer\documents\visual studio
2012\projects\downloader++\downloader++\main.c(151): error C2065:
'pCallback' : undeclared identifier
2012\projects\downloader++\downloader++\main.c(151): warning C4133:
'function' : incompatible types - from 'int *' to
'LPBINDSTATUSCALLBACK'
2012\projects\downloader++\downloader++\main.c(153): error C2065:
'url' : undeclared identifier
2012\projects\downloader++\downloader++\main.c(159): error C2065:
'url' : undeclared identifier
2012\projects\downloader++\downloader++\main.c(164): error C2065:
'url' : undeclared identifier 1>  Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Thank you :)

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Jork449
  • 97
  • 2
  • 6
  • 1
    "class" is not a valid keyword in C code. – brian beuning Apr 17 '13 at 23:41
  • Is there a way to convert the code so it works in c? – Jork449 Apr 17 '13 at 23:43
  • 2
    Not this code. You have to implement all the methods outside of the class (which would be a `struct` in C). Coding COM coclass objects in C is not impossible; just tedious, and there should be numerous examples of such on the web. The fundamental crux is you provide a structure of function pointers, and then implement them outside the struct definition. Not for the non-C-function-pointer savy feint of heart, but doable. – WhozCraig Apr 17 '13 at 23:46
  • Could you please give an example? – Jork449 Apr 17 '13 at 23:52
  • Usually you would compile the C++ code with a C++ compiler, and make some extern "C" functions your C code would call to work with the C++ code. – brian beuning Apr 18 '13 at 00:28

1 Answers1

0

A common technique is to write wrapper functions, where the pointer to your class instance is treated as a void* when passed to C. Then, you expose a function like say:

extern "C" MyClass_OnProgress(/* [in] */ void* instance, /* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR wszStatusText)
{
    MyClass* _this = static_cast<MyClass*>(instance);
    _this->OnProgress(ulProgess, ulProgressMax, ulStatusCode, wszStatusText);
}

note: the above is missing the return type because I've no idea what the STDMETHOD macro declares as the return value.

Also, drop the Hungarian notation. It's annoying and has fallen out of favor. Even Microsoft recommends against using it in new code.

Nathan Ernst
  • 4,540
  • 25
  • 38
  • i tried your recommendation ,but when compiling the compiler gives an error on the class (i renamed your MyClass MyCallback to much my code) also tried this extern "C"ULONG MyClass_OnProgress(/* [in] */ void* instance, /* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR wszStatusText) { MyCallback* _this = static_cast(instance); _this->OnProgress(ulProgress, ulProgressMax, ulStatusCode, wszStatusText); } – Jork449 Apr 18 '13 at 20:00