I am struggling at connecting two APIs. From one I get a Windows::Storage::IBuffer, and the other demands a ComPtr<IStream>. I do not seem to find a way to bridge these two, even if I wanted to do a copy of the data in the stream.
So far the only way forward from IBuffer is to create a Windows::Storage::Streams::DataReader::FromBuffer(buffer). From there, I can ReadBytes to get Platform::Array<unsigned char> array, but then what?
Thanks!
There may be other methods to get a COM compatible IStream interface for the IBuffer but if you have the data bytes you can create a COM IStream on memory using the CreateStreamOnHGlobal API then copying the bytes into the new IStream. Don't forget to reset the seek pointer before handing it out.
[DllImport("ole32.dll")]
private static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, out IStream ppstm);
System.Runtime.InteropServices.ComTypes stm;
if (CreateStreamOnHGlobal(IntPtr.Zero, true, out stm) == 0)
{
stm.Write( ...data for the stream... );
stm.Seek(0, 0, IntPtr.Zero); // seek to start of stream
}
Related
My overall goal is to capture the desktop screen and encapsulate in a webm container with encoding such as VP8 or VP9. I can save it as a file, but my intention is to stream the video to a webbrowser and using mediasource extension to view the content.
Now am stuck att writing/reading the data of memory using avio_alloc_context .
avio_alloc_context(ioBuffer, IOBUFSIZE, 1, nullptr, readFromBuffer, writeToBuffer, nullptr);
Does anyone have code snippets for both read and write functions?
From this question i found the write function:
std::vector<uint8_t> outputData;
int mediaMuxCallback(void *opaque, uint8_t *buf, int bufSize)
{
outputData.insert(outputData.end(), buf, buf + bufSize);
return bufSize;
}
How should the read function be implemented any idea?
Is a vector the best alternative or how about an IStream which one is easier?
I have build a set C++ containing classes on top of the BluetoothAPIs apis.
I can enumerate open handles to services, characteristics and descriptors. I can read characteristic values. The issue that I have is that I cannot write to a characteristic value.
Below is the code use to write the characteristic value
void BleGattCharacteristic::setValue(UCHAR * data, ULONG size){
if (pGattCharacteristic->IsSignedWritable || pGattCharacteristic->IsWritable || pGattCharacteristic->IsWritableWithoutResponse)
{
size_t required_size = sizeof(BTH_LE_GATT_CHARACTERISTIC_VALUE) + size;
PBTH_LE_GATT_CHARACTERISTIC_VALUE gatt_value = (PBTH_LE_GATT_CHARACTERISTIC_VALUE)malloc(required_size);
ZeroMemory(gatt_value, required_size);
gatt_value->DataSize = (ULONG)size;
memcpy(gatt_value->Data, data, size);
HRESULT hr = BluetoothGATTSetCharacteristicValue(bleDeviceContext.getBleServiceHandle(), pGattCharacteristic, gatt_value, NULL, BLUETOOTH_GATT_FLAG_NONE);
free(gatt_value);
if (HRESULT_FROM_WIN32(S_OK) != hr)
{
stringstream msg;
msg << "Unable to write the characeristic value. Reason: ["
<< Util.getLastError(hr) << "]";
throw BleException(msg.str());
}
}
else
{
throw BleException("characteristic is not writable");
}}
The call to bleDeviceContext.getBleServiceHandle() returns the open handle to the device info service.
pGattCharacteristics is the pointer to the characteristic to write too. It was opened with a call to BluetoothGATTGetCharacteristics.
I have tried different combinations of the flags with no difference in the return code.
I have also tried using the handle to the device not to the service. In that case I get an ERROR_INVALID_FUNCTION return error code.
I would appreciate any pointers as to what I am doing wrong or what other possible options I could try.
1- You have to use the Service Handle, right.
2- I don't know how you designed your class, and then how you allocate some memory for the Characteristic's Value itself.
What I do (to be sure to have enough and proper memory for Value's data):
a) at init of the Value object, call ::BluetoothGATTGetCharacteristicValue twice, to get the needed size and then actually allocate some internal memory for it.
b) when using it, set the inner memory to what it may , then call ::BluetoothGATTSetCharacteristicValue
hr=::BluetoothGATTSetCharacteristicValue(
handle,
(PBTH_LE_GATT_CHARACTERISTIC)Characteristic,
value,//actually a (PBTH_LE_GATT_CHARACTERISTIC_VALUE) to allocated memory
0,//BTH_LE_GATT_RELIABLE_WRITE_CONTEXT ReliableWriteContext,
BLUETOOTH_GATT_FLAG_NONE)
So a few things:
typedef struct _BTH_LE_GATT_CHARACTERISTIC_VALUE {
ULONG DataSize;
UCHAR Data[];
} BTH_LE_GATT_CHARACTERISTIC_VALUE, *PBTH_LE_GATT_CHARACTERISTIC_VALUE;
is how the data structure used in the parameter CharacteristicValue is defined. Please note that Data is NOT an allocated array, but rather a pointer. So accessing Data[0] is undefined behavior and could be accessing anywhere in memory. Rather you need to do gatt_value.Data = &data; setting the pointer to the address of the input parameter.
Secondly the documentation is quite clear as to why you might get ERROR_INVALID_FUNCTION; if another reliable write is already pending then this write will fail. You should consider retry logic in that case.
As for E_INVALIDARG I'd assume it's related to the undefined behavior but I'd check after fixing the other issues previously mentioned.
Is there a single standard C/C++ function which takes either a file handle/pointer or a pointer to an in-memory buffer and reads data from the file/buffer?
I have a function which pulls data from a file, performs operations on said data, and sends it out over a socket. I also have a function that takes data in the form of a char buffer, performs exactly the same operations on that data, and sends it over a socket. This problem isn't that hard. I just thought it would be convenient if there was a function like
read(void *dest, void *src, int src_type, size_t amount)
In C++ you can use std::istream as an abstraction on top of a file with an std::ifstream implementation, or an in-memory buffer with an std::istringstream implementation.
The beauty of this approach is that your function does not need to know about the implementation type, because receiving the argument by reference would be sufficient:
void readData(std::istream& in_data) {
...
}
The caller would then construct an appropriate implementation, and pass it to readData.
Sounds like you want to use the operator>>() on an input stream (std::istream), which can either be a filestream, a iostream or a stringstream
I don't know about windows but it will work in Linux.
void readif(int fd ,char *src,size_t nbytes){
read(fd,src,nbytes);
//error handler code
//Other stuffs
}
int fd = open(file);
//for std::input fd = 0
//for in memory data use mmap
mmap
open
read
I would like to serialize/deserialize some structured data in order to send it over the network via a char* buffer.
More precisely, suppose I have a message of type struct Message.
struct Message {
Header header;
Address address;
size_t size; // size of data part
char* data;
} message
In C, I would use something such as:
size = sizeof(Header) + sizeof(Address) + sizeof(size_t) + message.size;
memcpy(buffer, (char *) message, size);
to serialize, and
Message m = (Message) buffer;
to deserialize.
What would be the "right" way to do it in C++. Is it better to define a class rather than a struct. Should I overload some operators? are there alignment issues to consider?
EDIT: thanks for pointing the "char *" problem. The provided C version is incorrect. The data section pointed to by the data field should be copied separately.
Actually there are many flavors:
You can boost let it do for you: http://www.boost.org/doc/libs/1_52_0/libs/serialization/doc/tutorial.html
Overloading the stream operators << for serialization and >> for deserialization works well with file and string streams
You could specify a constructor Message (const char*) for constructing from a char*.
I am a fan of static methods for deserialization like:
Message {
...
static bool desirialize (Message& dest, char* source);
}
since you could catch errors directly when deserializing.
And the version you proposed is ok, when applying the modifications in the comments are respected.
Why not insert a virtual 'NetworkSerializable' Class into your inheritance tree? A 'void NetSend(fd socket)' method would send stuff, (without exposing any private data), and 'int(bufferClass buffer)' could return -1 if no complete, valid message was deserilalized, or, if a valid message has been assembled, the number of unused chars in 'buffer'.
That encapsulates all the assembly/disassembly protocol state vars and other gunge inside the class, where it belongs. It also allows message/s to be assembled from multiple stream input buffers.
I'm not a fan of static methods. Protocol state data associated with deserialization should be per-instance, (thread-safety).
I'm creating an IStream as follow:
IStream* stream;
result = CreateStreamOnHGlobal(0, TRUE, &stream);
Then I have a CImage object that I save to this stream:
image->Save(stream, Gdiplus::ImageFormatBMP);
I need to get the size of bytes written to this IStream.
How can I do this?
There is no Length or something like this in the IStream...
thanks!
IStream::Stat should do what you want.
Or you can use:
ULARGE_INTEGER liSize;
IStream_Size(pStream, &liSize);
other functions you might find useful in this context:
IStream_Reset(pStream); // reset seek position to beginning
IStream_Read(pStream, mem, size);
Both IStream_Size as well as IStream::Stat can be used to request the size. IStream_Size appears to be a convenience wrapper around IStream::Stat (that's oddly only available as a C COM macro). If that is indeed the case then there's a lot of data queried: An entire STATSTG, optionally without the pwcsName member.
In that case, a less costly way to get the same information would be IStream::Seek:
HRESULT get_size(IStream* stream, ULARGE_INTEGER& size) {
return IStream->Seek({}, STREAM_SEEK_END, &size);
}
This changes the stream's current read or write pointer. If you need to save the current position you can use the following:
ULARGE_INTEGER current{};
stream->Seek({}, STREAM_SEEK_CUR, ¤t);