-
Nov 23rd, 2024, 10:50 PM
#1
Thread Starter
Frenzied Member
How do I call functions in interfaces like IStorage from C?
I have a COM object (which is presented as a pointer to a struct in C, instead of a class as it would be in C++). So basically the object is a pointer to the IStorage interface, in my situation, and the declaration looks like "IStorage* s". So "s" is the variable in this case. So I tried to release the object with "s->Release(s)", and yes that is correct, as the function's only argument is a pointer to itself. But calling the function that way didn't work. I've seen code snipits before where accessing a member of a C struct when you only have a pointer to the struct, is done with the -> (minus greater than) symbol. I also tried using the syntax "s::Release(s)" because I've seen the :: (double colon) used in various snipits of C code to call functions when those functions are members of a struct (or possibly a pointer to a struct, I'm not really sure, since this is like really advanced C programming techniques I remember seeing the snipits of), but that didn't work either. All I know is that an Object is something that contains a number of things called interfaces, and IStorage is such an interface. The interface itself contains a pointer to a VTable (virtual function table), and that that VTable is a struct containing pointers to the functions. And I remember reading somewhere that in C, you can call function pointers just as if they were actual functions (no special calling syntax is needed for calling a function pointer, only for defining the function pointer). So I figured that if the function pointer is a member of a struct, I would only need to do normal struct member accessing syntax and combine that with with the normal function calling syntax. But that doesn't seem to be working.
-
Nov 24th, 2024, 12:26 AM
#2
Thread Starter
Frenzied Member
Re: How do I call functions in interfaces like IStorage from C?
Ok. I finally figured it out. Apparantly the standardized name of the VTable pointer that is found within the interface (itself a struct) is called lpVtbl. Using that, I was able to make this sample program here that generates a simple Compound Binary file (aka Structured Storage file). In the root storage, it contains a storage called MyStorage, and in that it contains a stream called MyStream. The data in the stream is the 15 character ASCII string "This is a test.". I posted the code below.
Code:
#include <objbase.h>
int main(){
IStorage* s = 0;
IStorage* s2 = 0;
IStream* stm = 0;
StgCreateDocfile(L"testfile.dat",STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,0,&s);
s->lpVtbl->CreateStorage(s,L"MyStorage",STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,0,0,&s2);
s2->lpVtbl->CreateStream(s2,L"MyStream",STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,0,0,&stm);
stm->lpVtbl->Write(stm,"This is a test.",15,0);
stm->lpVtbl->Release(stm);
s2->lpVtbl->Release(s2);
s->lpVtbl->Release(s);
return 0;
}
This code will compile with TCC (Tiny C Compiler) which is designed to be compatible syntax-wise, with GCC (the Linux C compiler). Note that before you compile it, you'll first need to make a DEF file (which is how it finds the exports of a DLL) for ole32.dll which will be called ole32.def (which is one DEF file it does not come with). The file will be generated when you run the command line "tcc -impdef ole32.dll". After that, copy the resulting DEF file to the "lib" folder. Then run the command line "tcc MAINFILENAME.C -lole32". And yes you avoid including the .def file extension here (it automatically adds the extension internally). And MAINFILENAME.C is just a placeholder for whatever you name the source code file into which you'll paste the code I posted above.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|