I mainly mean using pinvoke from within the dotnet library – in most cases we are talking about making a dotnet class, where each instance manages an corresponding native instance in the native library/application, and uses its properties and methods to forward calls to & from the native side via pinvoke, so that from dotnet it looks like a normal class, while in fact having little to no data or functionality of its own.
On the native side (in your native library that is hosting the clr), you may also end up writing some code there if it helps make things easier on the dotnet side (maybe some idioms used in the native api map poorly to dotnet, and you can make them a bit friendlier in this layer). Or in some cases you may want to write some native code for performance reasons.
That said, from your remarks it appears there may be some more fundamental things you will need to explore about native code and libraries. I’ll just make a few remarks hopefully to help. I’ll start from the beginning for clarity, just skip what you already know.
To begin with, we have (generally) .h and .cpp files – .h for headers, which declare an interface, and .cpp for the implementation (code) of that interface. The compiler compiles the implementation (into what is referred to as a translation unit), and puts it into an .obj file (again speaking generally). And a static library (.lib) is basically a file with a bunch of .obj files stuffed into it, which the linker can use, to save you from having to link hundreds of individual .obj files.
However, just to make life interesting, there are also .lib files which are basically empty, and which instead of containing any actual object code, instead basically contain offsets where functions may be found in an associated .dll. When you give this type of .lib (called an import library) to the linker, it just arranges to have calls made into the associated .dll, at runtime.
This implies that the .dll will be loaded at runtime, so that the required functions will actually be available, and this is where you come to LoadLibrary. Generally you do not have to call this yourself, as it will have been arranged to be handled automatically, as part of linking to the .dll’s .lib file.
So, the purpose of linking a .lib (we would say link, not include), whether an import library or not, is to allow the linker to hook up function calls to to the sites where those functions will be found at runtime, whether that is in the current executable, or in some .dll.
The general way of working, then, is to have a header, along with either a static lib, or an import lib with matching dll. You include the header in your code, and you give the lib to the linker (or link to it using #pragma comment(lib) as seen in Steve’s example). The compiler uses the header, trusting that implementations of the declared classes and functions will be available to the linker, and the linker looks in the lib to see if they are.
Now circling back to your remarks, unless you have a .h file declaring the signature of the functions you expect to be able to use, then you are not going to have much fun, since without a header, you would need to have some other way of knowing the exact signatures of the functions you intend to use, as implemented in the executable where you expect them to exist.
However it’s not really clear to me, your actual situation, since on one hand you say you are able to have the closed application load a dll, while on the other, you seem to be looking for some way to use a dll directly, without a header. At any rate, I hope this info is of some use to you.